I am not new to MySQL but a strange situation happened in my code today coincidently which got me surprised. Can someone explain why this gives me identical results?
SELECT * FROM `products` WHERE id = 12
and
SELECT * FROM `products` WHERE id = '12ABC'
In both cases I get the same result with the same record being selected. I would expect that second one would return me nothing?! My ID field is int(11) unsigned with auto_increment flag turned on.
From MySQL docs:
When an operator is used with operands of different types, type conversion occurs to make the operands compatible
Documentation
So basically, '12ABC' is cast to 12.
MySQL has to make a conversion to make a compare betwen 2 different types. It tries to make the string to an int and get the digits from the string starting from the beginning.
It you had for instance
'ABC12'
the result of the string conversion to int would be 0
Related
Why if I run a query with gibberish at the end of the where condition it incorrectly returns a result.
Example:
SELECT * FROM contractor_table WHERE contractorID = '97sd'
I am getting the row with the ID 97, when I should get no result.
What is happening here is that you are comparing the contractorID column, which is integer or some other numeric type, against a string literal 97sd. This doesn't make any sense, so MySQL, based on its casting rules, attempts to first cast 97sd to an integer. Consider the result of the following query:
SELECT CAST('97sd' AS unsigned);
In fact, this outputs just 97, the integer. So, in practice this means that the "gibberish" at the end of your string literal, which begins with an integer, will be ignored by MySQL.
But best practice here is to always compare columns against the correct literal types. So use the following version always, for best results:
SELECT * FROM contractor_table WHERE contractorID = 97;
This happends when you have column type int or other numeric if you convert it into varchar than it will retun no output
When I'm searching a specific row by:
SELECT * FROM table WHERE id = '0003'
Wherein column id is an INT primary key field, and it returns me the row of id = 3
Again if I search by:
SELECT * FROM table WHERE id = '3df'
It still returns me the row of id = 3
This is really weird. Why?
My Mysql version is 5.7.14 community.
MySQL does implicit conversion of strings to numbers, in a numeric context.
It does so by converting the leading digits, and stopping at the first non-digit. Most databases would return a type conversion error.
The moral? Always ensure that the types are compatible before doing such a comparison. If you like, you can change this to an explicit case:
where id = cast('3df' as unsigned)
In this case, you will get the type conversion error.
i'm working with mysql in a nodejs web app. I don't understand why when I ask for some id (key) it gives me more than 1 result.
When I:
SELECT * FROM products WHERE id = 1;
This happens, I get 3 results, but I only want 1:
1, 001 and 0000001.
I just want the info of one product (id: 1 in this example)
How can I fix this?
ID type is varchar(20)
If I use LIKE instead of = my result changes:
SELECT * FROM products WHERE id LIKE 0000001;
I get the info of id = 1 instead 0000001. Don't know why.
Thanks
The WHERE clause of your query contains a comparison of a literal numeric value with a string (column id).
When it needs to compare values of different type, MySQL uses several rules to convert one or both of the values to a common type.
Some of the type conversion rules are not intuitive. The last rule is the only one that matches a comparison of an integer number with a string:
In all other cases, the arguments are compared as floating-point (real) numbers.
When they are converted to floating-point (real) numbers, 1 (integer), '1', '0001' and '0000001' are all equal.
In order to get an exact match the literal value you put in the query must have the same type as the column id (i.e string). The query should be:
SELECT * FROM products WHERE id = '1'
The problem is that you are looking by a varchar type using an integer cast.
Try to add quotes to the id parameter:
SELECT * FROM products WHERE id = '1';
If you want to add integer ids with with leading zeros, I recommend you to use the zerofill option:
https://dev.mysql.com/doc/refman/5.5/en/numeric-type-attributes.html
If you want to use use alphanumeric values then keeps the ID type as varchar, but remember to enclose the search param into quotes.
Numbers in MySQL (and the real world) don't have leading zeros. Strings do.
So, you just need to make the comparison using the right type:
SELECT *
FROM products
WHERE id = '1';
What happens with your original query is that the id is converted to a number. And '1', '001' and '0000001' are all converted to the same integer -- 1. Hence, all three pass the filter.
Wondering what's wrong with comparing BIGINT column values with '1'. Exactly, why this isn't producing any results:
SELECT * FROM table WHERE col = '1'
while this works just fine (i.e. returns non-empty result).
SELECT * FROM table WHERE col = 1
Thanks
If you are comparing an integer, you do not need quotes around it.
This appears to possibly be an unresolved bug.
See MySQL Bugs
You don't need to use quotes in comparing with Int or BigInt.
But I am getting result even I am comparing with quotes.
See this fiddle
I'm experiencing a strange problem..
I got a table with the following fields:
id smallint(5)
client_id smallint(5)
name varchar(50)
pass varbinary(20)
I got at row with the following values:
id = 5
client_id = 10
name = 'user'
pass = '123'
But if I put some chars in after the client_id it still returns the row???
This query ought not to return anything... hmm
SELECT id
FROM db.user
WHERE client_id='10ddd' && name='user' && pass='123'
That's because mySQL auto-casts string values that are meant for int columns, cutting off all non-integer content.
In the process, 10ddd gets truncated to 10.
See 11.2. Type Conversion in Expression Evaluation
I thought it's possible to turn off using one of the stricter server modes, but I can't see anything in the docs. Failing that, I'm not aware of a simple workaround!
Depending on where the value comes from, you could do a check on the value before you do the query, e.g. using is_int() if in PHP; exit if the value is not an integer.