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.
Related
if I have an int column of id, is it bad for performance to have a query written like
SELECT * FROM products where id = '1'?
Or does MySQL handle this the same as
SELECT * FROM products where id = 1
In general: don't do this. Compare values against a literal of the correct datatype, so you don't have to worry about what is going on under the hood. If you have an integer column, then:
SELECT * FROM products WHERE id = 1
In this specific situation: when asked to compare a number to a string, MySQL converts the string to a number. So there would be (almost) no performance penalty if you were to use:
SELECT * FROM products WHERE id = '1'
The literal string is converted once, and then checked against every value in the column.
On the other hand, consider a string column, say str, and a predicate like:
WHERE str = 1
Now it goes the other way around. MySQL needs to convert all string values in str to numbers before they can be compared. The expression becomes inefficient - it cannot take advantage of an index (it is non-SARGable). If there are many rows, the performance impact may be important.
So, back to the initial recommendation: know your datatypes; use the proper literal when comparing.
If performance is your concern, numbers are smaller than text in this example--1 is faster than "1".
HOWEVER... if you're looking for performance never start with SELECT *
The cases:
WHERE int_col = 2 -- Good
WHERE int_col = "2" -- Good; the "2" is turned into INT at start of query
WHERE int_col = "2foo" -- Probably not what you wanted
WHERE char_col = 2 -- Slow; `char_col` is turned into INT for each row
WHERE char_col = "2" -- Good
I am new in Mysql and have a table where I'm going to select based on an integer column, the problem is that when I use an string on this column! I got no error but it gives me back all rows. for example:
SELECT * FROM `News` WHERE Cat='hello' order by id desc limit 20
It gives me 20 rows! what's wrong? did I do anything wrong or it's because of something else?
This is normal behavior for MySql, because in this expression:
Cat='hello'
what happens is an implicit conversion of the string literal 'hello' to INTEGER and as it is described in Type Conversion in Expression Evaluation the result of this conversion is 0, so the expression is equivalent to:
Cat=0
If you want to prevent this conversion you could instead convert the column Cat to string:
WHERE CONVERT(Cat, CHAR) = 'hello'
This way the comparison of Cat and 'hello' will be alphanumerical and will fail.
But if you pass a valid integer, then the correct result will be returned.
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
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.
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