I had an issue with a MySQL statement that was returning null all the time, and although I was able to figure it out, the cause left me a bit puzzled.
This is a simplified version of the problematic query:
SELECT id FROM users WHERE id = id = 2;
The error happened because id =
is repeated, removing one of the id =
solved the problem (as there is a user with the id 2). But what has me a bit confused is how it "fails silently", returning 0 rows, instead of giving an error.
I tested a similar query on SQL Server, and got the error message Incorrect syntax near '='
(something similar to what I would have expected from MySQL).
Originally, I thought that MySQL was making a comparison between the first two fields and the last one was the result of the comparison (with 0 for false, and 1 for true). Something like this:
SELECT id FROM users WHERE (id = id) = 2;
But then I ran some queries that (kind of) contradicted that. Let me elaborate a bit more.
Imagine this table (called "users"):
id | username
----|----------------
0 | anonymous
1 | root
2 | john
3 | doe
If I do SELECT * FROM users WHERE id = id = 1
, I get all 4 users. And with SELECT * FROM users WHERE id = id = 0
, I don't get any. That seems to confirm the comparison theory. But, things get confusing if I do something like this:
SELECT * FROM users WHERE id = username = 1;
SELECT * FROM users WHERE id = username = 0;
None of the records have the same id as username (they are not even the same type: int(11)
and varchar(25)
respectively), but with the first one, I get one result back: "anonymous". And with the second one, I get all the users but "anonymous". Why does that happen? I see that it has something to do with the id
being 0, because if I replace "anonymous'" id from 0 to 4, then I don't get it anymore with the first query (and it shows up in the second).
I guess it has to do with MySQL turning strings/varchars into 0 when comparing with numbers. But why does it permit chained comparisons in the same clause? What order does it follows when comparing them?
Things get funny when queries like this are valid, and actually return (unexpected?) values. For example:
SELECT * FROM users WHERE id = id = id = username = username = id = username = 1;
returns the records with id 2 and 3, but no the ones with id 0 and 1. Why is that?
tl;dr version: Why do queries with chained comparison operation work? What is the order followed in the comparisons? Is this a bug or the expected behavior?
- A SQLFiddle with the database and the last query: http://sqlfiddle.com/#!9/4f2ab/4