Codeigniter Active records complex query - mysql

> *1. I need to write this in Active records *
i need to join these 3 tables , but the condition for join is very very selective
$this->db->select(name);
$this->db->from('table0');
$this->db->join('table1','(table1.id=0 AND table0.feild1 = table1.feild1) OR (table1.id=1 AND table0.feild2 = table1.feild2)') // <--- how to write this is my question
i could do a simple join but the main problem is achieving the condition in the join that i have mentioned above.Also this is a small part of a very , very ! big query so i really cant change it back to the native sql query like :
$this->db->query('//entire sql query'); //cant do this, need to write ACTIVE RECORDS
when i write the active records , firebug throws me an error saying :
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near ') OR
any suggestions ?

To be honest, I don't know that it is possible. CI doesn't use true Active Records, so each method has very rigid parameters, and I don't see any that can be tricked into performing the task you need.
What I would try is re-writing your query a bit:
$this->db->select(name);
$this->db->from('table0');
$this->db->join('table1','(table1.id=0 AND table0.feild1 = table1.feild1)', LEFT);
$this->db->join('table1','(table1.id=1 AND table0.feild2 = table1.feild2)', LEFT);
$this->db->where('(table1.id=0 AND table0.feild1 = table1.feild1)');
$this->db->or_where('(table1.id=1 AND table0.feild2 = table1.feild2)');
I believe this query would return the correct values, but you'll certainly want to thoroughly test it. Hope this at least points you in the right direction.

Related

Correct MariaDB Syntax for SQL Replace Statement

After trying to determine why my SQL statement was returning an error in the Node code I am refactoring to connect to MariaDB rather than via SQL Anywhere, I have narrowed it down to the REPLACE statement we use to compute how many records to process, and how many to skip.
My initial test SQL SELECT statement looks like this:
SELECT customer_name FROM ar.customers
We then use a REPLACE statement to, as I say, determine how many records to process, and how many to skip. When we were using SQL Anywhere that looked like this:
const sql = this.query.replace(/SELECT/i, `SELECT TOP ${recordsPerRun} START AT ${recordsProcessed + 1}`);
That syntax needs to change because MariaDB uses "LIMIT" instead of "TOP". And from my understanding, the first parameter will be the number of records to skip, and the second one how many to return.
So, in my case, it'd be something like:
LIMIT ${recordsProcessed}, ${recordsPerRun}
However, I can't quite get the full syntax right. How can I write this REPLACE statement in a way that will work with my initial test SQL SELECT statement from above? This seems tricky to do since in MariaDB LIMIT now goes at the end of the query, not at the beginning, like TOP did for MySQL.
LIMIT goes at the end, so there's nothing to replace, just concatenate it:
const sql = this.query + ` LIMIT ${recordsProcessed}, ${recordsPerRun}`;
or combine it into the template:
const sql = `${this.query} LIMIT ${recordsProcessed}, ${recordsPerRun}`;

IF condition MySQL not working

I am trying to execute a query into MySQL but it keeps telling me i am using the wrong syntax, I tried searching the MySQL community but I am not getting anything usefull.. most of the answers i find on google are for other databases yet they label them for "MySQL", yet it keeps failing.
This is the statement i am trying to execute:
$statement = "IF (SELECT ttb_id FROM timetable WHERE ttb_week = $i AND ttb_time = $j) THEN
BEGIN
UPDATE types SET typ_name = '$subj'
WHERE typ_name = 'student';
END;
ELSE
BEGIN
INSERT INTO types VALUES (null,`Yo`);
END;
";
error:
ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF (SELECT ttb_id FROM timetable WHERE ttb_week = 0 AND ttb_time = 0) THEN ' at line 1
I am using:
PHP Script Language Version 5.2.6
MySQL Database Version 5.0.51b
I have been looking around but to no avail, and the if condition stated on the MySQL dev website are not helping at all..
I am new to this and it is driving me mad! all the different queries i tried failed.. it is never the right syntax.
I found many answers for the problem on stackExchange and other websites but it is always wrong.. also I remember this structure from a VB.net lesson a while ago so maybe this is for MSSQL? then what about MySQL? everyone so far listed similar structure and said it works for MySQL, I took my answer from an answer on this community* labeled for MySQL and he claimed it worked. this is one of many i tried.
I would really appreciate your help
*: Usage of MySQL's "IF EXISTS"
My first thought would be you're not comparing your SELECT return to anything to actually utilize your conditional logic. Are you just looking to see if your query returns values? If it doesn't return a value then you insert a new record in otherwise you update.
Maybe use IS NOT NULL or a check to see count on the select to see how many rows and compare to see if that's greater than 0.
IF (SELECT ttb_id FROM timetable WHERE ttb_week = $i AND ttb_time = $j IS NOT NULL) THEN
IF (SELECT COUNT(*) FROM timetable WHERE ttb_week = $i AND ttb_time = $j) > 0 THEN

what is wrong with this line of SQL?

SELECT Batch.NumStud
FROM Batch
WHERE CourseID='$courseid'
INNER JOIN Course
ON Batch.CourseID=Course.CourseID"
an error that says mysql_fetch_array(): supplied argument is not a valid MySQL result resource in <b>F:\AppServ\www\anNoECourse.php
is shown.This code was written to feed in data to a google chart.
You put SQL in wrong order (JOIN and WHERE are switched):
SELECT Batch.NumStud
FROM Batch INNER JOIN Course
ON Batch.CourseID = Course.CourseID
WHERE Course.CourseID = '$courseid'
It seems, that your query can be simplified (check your data):
select Batch.NumStud
from Batch
where Batch.CourseID = '$courseid'
I think the error is a bit more complex. Due to the fact that your SQL is invalid, you're not getting a result set. This case is not handled correctly by your PHP code!
So in addition to correcting your SQL as the others have suggested, please make sure to handle the case where you get no results or your query results in an error correctly in your PHP code!
The second part to your solution is as follows:
$result = mysql_query(...);
if ($result)
{
while (...)
...
}
This makes sure that mysql_query actually returned a result set and not false, which it does in case of errors (due to your invalid SQL code, but also in other cases). So just fixing your SQL is not enough to make your script error proof.
But again, do no longer use the mysql_.... functions! They are deprecated.

Why isn't my SQL LEFT JOIN query working?

It is returning 0 rows when there should be some results.
This is my first attempt at using JOIN but from what I've read this looks pretty much right, right?
"SELECT pending.paymentid, pending.date, pending.ip, pending.payer, pending.type, pending.amount, pending.method, pending.institution, payment.number, _uploads_log.log_filename
FROM pending
LEFT JOIN _uploads_log
ON pending.paymentid='".$_GET['vnum']."'
AND _uploads_log.linkid = pending.paymentid"
I need to return the specified values from each table where both pending.paymentid and _uploads_log.log_filename are equal to $_GET['vnum]
What is the correct way to do this? Why am I not getting any results?
If someone more experienced than me could point me in the right direction I would be much obliged.
EDIT
For pending the primary key is paymentid, for _uploads_log the primary is a col called log_id and log_filename is listed as index.
Try this
SELECT pending.paymentid,
pending.date,
pending.ip,
pending.payer,
pending.type,
pending.amount,
pending.method,
pending.institution,
payment.number,
_uploads_log.log_filename
FROM pending
LEFT JOIN _uploads_log
ON _uploads_log.linkid = pending.paymentid
WHERE _uploads_log.log_filename = '" . $_GET['vnum'] . "'
Your current query is vulnerable with SQL Injection. Please take time to read the article below.
Best way to prevent SQL injection in PHP?
The ON clause only should have the condition to link the two tables especially if it is LEFT JOIN. The WHERE clause then has the actual condition. Otherwise you will get nothing if there is no corresponding entry in _uploads_log. It also is more easy to read in my opinion.
As another remark. It is always better to work with bind parameters to avoid SQL injection.

Hibernate Exception on MySQL Cross Join Query

I'm trying to perform a bulk delete of an object, Feature, which has a birdirectional ManyToOne relationship with another class, FeaturesMetadata. I'm having a SQLGrammerException thrown.
The hql I'm using:
String hql = "delete from Feature F where F.featuresMetadata.stateGeoId = :stateGeoId";
Turning on show SQL, the following is generated:
delete from FEATURE cross join FEATURESMETADATA featuresme1_ where STATEGEOID=?
Running the SQL directly in the db client gives this exception:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'cross join FEATURESMETADATA featuresme1_ where stategeoid='01'' at line 1
Since the generated SQL is throwing the Exception, I tried changing dialects from MySQL5InnoDBDialect to MySQLInnoDBDialect, but no change.
Can anyone assist?
You may not have joins in such a HQL query. Quote from the reference documentation:
No joins, either implicit or explicit, can be specified in a bulk HQL
query. Sub-queries can be used in the where-clause, where the
subqueries themselves may contain joins.
So I guess something like this should work:
delete from Feature F where F.id in
(select f2.id from Feature f2 where f2.featuresMetadata.stateGeoId = :stateGeoId)
I had the same issue and struggled to find a sensible answer. It seems that, even if you get this approach to work, the SQL generated is highly inefficient (according to what I have read).
So I took a step back and did the following:
List<Properties> props = propDao.findPropertiesByHotelCode(hotel.getCode());
propDao.deleteInBatch(props);
propDao.flush();
Basically rather tan trying to 'delete where', I'm doing a select where and then deleting in batch the set that I retrieved.
Hope this helps.
This is indeed rather poor from Hibernate. But you can solve it like this in a repo: (at least in PostgreSQL, not sure if this syntax should be modified for MySql)
#Modifying
#Query(nativeQuery = true, value = """
DELETE FROM feature f
USING features_metadata fd
WHERE f.features_metadata_id = fd.id AND fd.state_geo_id = :stateGeoId
""")
void deleteByStateGeoIdId(#Param("stateGeoId") UUID stateGeoId);