Laravel SQL is not performing as expected. No syntax error - mysql

Can any Laravel developers help me understand why the following SQL statement is not working. I don't get any errors, it simply doesn't do what it should:
DB::table('devices')
->leftJoin('hotel_device','hotel_device.device_id','devices.id')
->where("hotel_device.device_id","IS","NULL")
->delete();
This should remove all device ids where the leftJoin link returns as NULL (ie. where this device id is not being used in the "hotel_device" table).
If I run it as raw SQL directly in the database it works correctly. Note the "IS" condition rather than "=" condition, as I am refering to a NULL value. (using "=" didn't find any matching rows)
thanks.

You should use the whereNull method to compare to null rather than trying to filter it using the regular where method.
DB::table('devices')
->leftJoin('hotel_device','hotel_device.device_id','devices.id')
->whereNull("hotel_device.device_id")
->delete();

Related

Symfony 2 - Doctrine ORM Update query not working

I am trying to update a mysql table with following query using Doctrine. But the table is not get updated. Also below code didnt throw any error. I am totally confused. If i run the query, taken from getDQL() method, in mysql directly it showing 0 rows updated becuase of inproper qoutes. it is working after placed proper qoutes for values in the query. Need help to solve this puzzle.
Since i am new to doctrine, i will use the examples give in querybuilder class file.
$support = $this->createQueryBuilder('p')
->update('gcns', 'g')
->set("g.isActive", "0")
->andWhere("g.issn='".$issn."'");
Do you ever execute the query or are you just building it? You should have something along these lines to execute it:
$support->getQuery()->getSingleScalarResult();
If i run the query, taken from getDQL() method, in mysql directly it showing 0 rows updated becuase of inproper qoutes.
getDQL() returns DQL not SQL, so it will have improper quotesif you try to run it directly inside MySQL, but that's expected.
You shouldn't concatenate $issn into your query. You should use parameters instead:
$qb = $this->createQueryBuilder()
$support = $qb->update('gcns', 'g')
->set('g.isActive', '0')
->andWhere( $qb->expr()->eq('g.issn', ':issn') )
->setParameter( 'issn', $issn )
->getQuery()->getSingleScalarResult()
;

Why is my query wrong?

before i use alias for table i get the error:
: Integrity constraint violation: 1052 Column 'id' in field list is ambiguous
Then i used aliases and i get this error:
unknown index a
I am trying to get a list of category name ( dependant to a translation) and the associated category id which is unique. Since i need to put them in a select, i see that i should use the lists.
$categorie= DB::table('cat as a')
->join('campo_cat as c','c.id_cat','=','a.id')
->join('campo as d','d.id','=','c.id_campo')
->join('cat_nome as nome','nome.id_cat','=','a.id')
->join('lingua','nome.id_lingua','=','lingua.id')
->where('lingua.lingua','=','it-IT')
->groupby('nome.nome')
->lists('nome.nome','a.id');
The best way to debug your query is to look at the raw query Laravel generates and trying to run this raw query in your favorite SQL tool (Navicat, MySQL cli tool...), so you can dump it to log using:
DB::listen(function($sql, $bindings, $time) {
Log::info($sql);
Log::info($bindings);
});
Doing that with yours I could see at least one problem:
->where('lingua.lingua','=','it-IT')
Must be changed to
->where('lingua.lingua','=',"'it-IT'")
As #jmail said, you didn't really describe the problem very well, just what you ended up doing to get around (part of) it. However, if I read your question right you're saying that originally you did it without all the aliases you got the 'ambiguous' error.
So let me explain that first: this would happen, because there are many parts of that query that use id rather than a qualified table`.`id.
if you think about it, without aliases you query looks a bit like this: SELECT * FROM `cat` JOIN `campo_cat` ON `id_cat` = `id` JOIN `campo` ON `id` = `id_campo`; and suddenly, MySQL doesn't know to which table all these id columns refer. So to get around that all you need to do is namespace your fields (i.e. use ... JOIN `campo` ON `campo`.`id` = `campo_cat`.`id_campo`...). In your case you've gone one step further and aliased your tables. This certianly makes the query a little simpler, though you don't need to actually do it.
So on to your next issue - this will be a Laravel error. And presumably happening because your key column from lists($valueColumn, $keyColumn) isn't found in the results. This is because you're referring to the cat.id column (okay in your aliased case a.id) in part of the code that's no longer in MySQL - the lists() method is actually run in PHP after Laravel gets the results from the database. As such, there's no such column called a.id. It's likely it'll be called id, but because you don't request it specifically, you may find that the ambiguous issue is back. My suggestion would be to select it specifically and alias the column. Try something like the below:
$categories = DB::table('cat as a')
->join('campo_cat as c','c.id_cat','=','a.id')
->join('campo as d','d.id','=','c.id_campo')
->join('cat_nome as nome','nome.id_cat','=','a.id')
->join('lingua','nome.id_lingua','=','lingua.id')
->where('lingua.lingua','=','it-IT')
->groupby('nome.nome')
->select('nome.nome as nome_nome','a.id as a_id') // here we alias `.id as a_id
->lists('nome_nome','a_id'); // here we refer to the actual columns
It may not work perfectly (I don't use ->select() so don't know whether you pass an array or multiple parameters, also you may need DB::raw() wrapping each one in order to do the aliasing) but hopefully you get my meaning and can get it working.

MySQL Query Error Validation

I running a Mysql Query to select some data, Sometimes i get a error called
mysql_fetch_assoc() expects parameter 1 to be resource, boolean given
when i executed this following code,
$result = $this->db->execute($sql);
for ($i = 0; $data[$i + 1] = mysql_fetch_assoc($result); $i++);
array_pop($data);
how do i optimize this coding to prevent any errors ?
is there anything wrong with it ? should i ignore this error ?
That means that the query is buggy, whyever, most likely because you construct it using components from sources which you do not really check enough. A buggy statement throws an error (since no result can be computed). That error is returned as false instead of a mysql result ressource. Since you do not check if the query succeeded but blindly try to retrieve details from the result, you get this second error.
So there are four things you have to invest into:
you should always check if a query succeeded at all:
enclose your query into a conditional: if (FALSE!==($result=$this->db->execute($sql))) and only retrieve from the result ressource if that condition resolves to true.
make sure you really (really!) check all input data you use to construct your query. Checking here also means to encode and escape it correctly, also see point 4. for this.
in cases like this it is important to analyze what exactly it is that is going wrong. There is little sense in guessing what might be going wrong. So in addition to checking if the query succeeded at all (1.) you should also take a look at the error message mysql throws if this is not the case. Use the method mysql_error() for this. It is well documented just as every other function too.
you should rework your code and migrate from phps old, long deprecated mysql extension to either mysqli or PDO. Both are php extensions that offer more security against constructing buggy statements. Read about "prepared statements" and "parameter binding" for this.

Replace IIf with SWITCH in WHERE clause

I have the following query in MS-Access 2003 and it works OK:
SELECT tblDiscounts.DiscountID, tblDiscounts.DiscountPercent, tblDiscounts.DiscountName, tblDiscounts.DiscountDescription
FROM tblDiscounts, qryPropertyPeriodRate_Count_Nested
WHERE (tblDiscounts.DiscountID) = IIf ([qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=1,1,IIf([qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=2,2,IIf([qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=3,3,4)));
I wish to replace the IIf function with the Switch function but whatever I tried didn't work. My best approach is the following:
SELECT tblDiscounts.DiscountID, tblDiscounts.DiscountPercent, tblDiscounts.DiscountName, tblDiscounts.DiscountDescription
FROM tblDiscounts, qryPropertyPeriodRate_Count_Nested
WHERE (((tblDiscounts.DiscountID)=SWITCH ([qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=1,1, [qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=2,2, [qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]=3,3, [qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]>3,4)));
but I get a message
Type mismatch in expression
Please advise!
One difference I can see is that if [qryPropertyPeriodRate_Count_Nested].[CountOfWeeks]<1 the nested IIfs will return 4 while the Switch statement will return Null. Check your underlying data to see if that could happen; a Null value might very well mess up the WHERE clause.

how to use string left function in hql

I have a sql query like this
select column from table where path = left('INPUTSTRING', length(path));
and trying to accomplish it in hql like this,
return session.createQuery("from Table where Path = left(:input, length(Path))").
query.setParameter("input", inputPath).
.list();
and getting an error like this
Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected token: left near line 1
how to get this done? What is the corresponding string function in hql? Is there a solution for this using criteria query apis?
Yes, left() is not supported by the MySQLDialect. See the list of HQL supported functions on API docs.
Now you have left with 2 options.
Use session.createSQLQuery() method.
Create Your own Dialect class by extending the MySQLDialect and register the function there. This is told at hibernate forum here explained well in a blog post here.
I'm not sure if HQL does this for you , but you can use IQuery/session.CreateSQLQuery() to use a raw SQL query to populate a mapped entity. I've never used it for substrings, but have used it for aggregate functions. Check chapter 13 of the NHibernate docs and see if that does it for you. You can check the query substitution available in Nhibernate - here