mysql : avoid automatic cast of string in integer in where clause - mysql

In my application, I use a generic where clause to search in different fields.
My request is like this :
SELECT * FROM command WHERE id = :search OR name LIKE %:search%;
I am searching the text "2SAV".
this request return some records where name contains "2SAV" (what I want) but also the record where id=2.
If I do more tests, I notice that :
SELECT CAST("2SAV" AS SIGNED); //2
SELECT 2="2SAV"; //1
If the string start with an integer, this part of string is kept.
Have you got an option or workaround to avoid this comportment?
Thanks in advance,

In the MySQL documentation( https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html) is stated:
In all other cases, the arguments are compared as floating-point (real) numbers.
I think you could cast in the query:
SELECT * FROM command WHERE id = cast(:search as char) OR name LIKE %:search%;

Related

MySql SELECT found row when WHERE doesn't match

I have a pretty simple table called roles:
When I ran SELECT * FROM roles WHERE role_id = "1ojosd041l"(the WHERE clause clearly didn't match with any row in the table). It somehow returned this:
Does anyone know why this is happening? My guess is that my role_id column is of type int, but I passed a string into the WHERE clause, so the str to int conversion produced something weird (like a 0 or 1).
I'm just looking for an official explanation for this. If anyone knows why this happens please let me know! Thank you!
Where MySQL expects a number, it will convert a string to a number, and ignore any leading whitespace or trailing garbage.
If you want to avoid this, do something like
SELECT * FROM roles WHERE role_id = "1ojosd041l" and concat(role_id) = "1ojosd041l"
Just the second condition would be enough but leaving the first condition in allows an index to be used.
There is somee MySQL magic happening here. MySQL sees that role_id is numeric. So it converts your string '1ojosd041l' to a number. This string isn't a number obviously, and MySQL should throw an error. But MySQL just takes as many digits as it finds from the left side of your string instead, so it gets number 1. (If your string started with a non-digit, then MySQL would even return a zero.)

SQL get row by int | string

Im little bit stucked with my SQL query.
I've got a table with rows that can be identified by id or hash string...
id
short
title
1
asdadasdsd
foo
2
1qweqweqwe
bar
3
yxcyxcyxcy
baz
So SQL is quite easy...
SELECT * FROM table WHERE id=<identifier> OR hash=<identifier>
What I found out is that when my identifier is hash and begins with number which could be found in the id column, MYSQL returning me "wrong" row.
For example when my identifier is "1qweqweqwe" result is row 1.
I think the reason for that is it converts my hash string into integer maybe? Is there a way how to disable this behaviour?
Or the only way is to regenerate all hashes into new formats without numbers in it?
Thank you for any clarification :)
Petr
No, you do not have to regenerate the hashes. If both the id and hash match and you prefer
to pull row based on hash, then you could have the hash as the first match column condition. Basically it goes with the first match condition that is found to be true.
Also, I suppose you are already adding quotes to the hash string in the query. If not please do, as it will validate as a string then.
SELECT * FROM table WHERE hash='<identifier>' OR id=<identifier>
You seem to be passing the identifier in as a string -- because it is. But then you are comparing to a number (the id) and the string parameter is converted to a number. MySQL does so by converting the leading digits, if any.
I don't like the logic of passing in a string for an identifier, so I would really suggest that you fix the calling logic and call either:
WHERE id = <int identifier>
or:
WHERE hash = <string identifier>
But if you want to keep your current version, you can convert to a string:
WHERE CAST(id AS CHAR) = <identifier> OR hash = <identifier>

Unexpected behaviour of SELECT when value being looked for is number followed by letters

I have a simple table:
Entity
ID : int
Name : varchar(10)
I was looking up entities by their ID and found a result that surprised me. Let's assume that an entity with ID = 10 exists. When I run the following queries, I get the following results:
SELECT * from Entity WHERE ID = 10 Found Entity 10 (as expected)
SELECT * from Entity WHERE ID = '10' Found Entity 10 (as expected)
SELECT * from Entity WHERE ID = A Syntax error (as expected)
SELECT * from Entity WHERE ID = 'A' Zero records found (as expected)
SELECT * from Entity WHERE ID = 10A Syntax error (as expected)
SELECT * from Entity WHERE ID = '10A' Found Entity 10 (WTF)
The final query would appear to ignore the 'A' and evaluate the query as if I had just passed in 10. This is not what I expected.
Is this standard behaviour? I cannot find any doco either way.
Yes, it's standard behavior for MySQL.
It's documented under Type Conversion for Expression Evaluation.
When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly. For example, MySQL automatically converts numbers to strings as necessary, and vice versa.
Casting a string to a number results in truncating it at the first non-numeric character, or 0 if the first character is not numeric.
See also: Can I configure MySQL's typecasting to consider 0 != 'foo'?
Note also that the '10A' query (and the 'A' one also) should have thrown a warning. SHOW WARNINGS; after the query to see it. Your client should have alerted you to the fact that a warning was thrown. If it didn't, you should complain loudly to the vendor, because that's broken behavior.
When casting a text value to an int, as MySQL does here with your text literals before looking up the id, its behaviour is to use all the numbers up to the first non-number.
Text values that don't have any numbers before the first non number (ie they start with a non number) get cast to 0.
I couldn't find a reference that declared this behaviour as a contract, but here's an SQLFiddle that shows it in action.

MySQL query enclosing numbers in strings

Suppose I have a query
SELECT * FROM table WHERE x > y;
where "y" is a user-input value. I'd like to enclose y in quotes. So far as I've tested, the query works properly when the quotes are added. Is the behaviour defined? Is it known to result in an efficiency drop?
Note that the query is an example fabricated for simplicity. Also, this is not an attempt to deal with SQL injection.
If the field that you are trying to compare with is a numeric field ie int, then all the possible combinations must work in mysql
select * from users where id = 20;
select * from users where id = "20";
select * from users where id = '20';
Refer the MySQL DOC for more depth
The conversion behavior of MySQL when comparing different types is well-defined. When a string and a number are compared, both are converted to floats. It's outlined in the manual, ยง 11.2.
IMO, you can try :-
cast( "-10" as signed )
This is casting in mysql (the function name is cast, obvious?).

how to query a blob data

I have a table like :
------------------------------
Test_Id Test_data
(String) (blob)
------------------------------
I want a query to retrieve all the Test_Id's for a matching Test_data.
To achieve something like : select * from test_table where Test_data = blobObject;
How can we do above ??
First: there's no such thing as a string in MySQL. Only char/varchar/text.
Well you could cast it as char for comparison like this:
select * from test_table where Test_data = CAST( blobObject AS CHAR );
what's probably better is to convert your string to a binary string, but this might not give you the right comparison if you expect string comparison behaviour... well best you have a look at the char functions here:
http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
You can use a hash function such as MD5
SELECT * FROM example_table WHERE MD5(blob_column) = 'a6a7c0ce5a93f77cf3be0980da5f7da3';
MySQL has data types which can store binary data. Not only char/varchar/text, but also BINARY/VARBINARY/BLOB.
See http://dev.mysql.com/doc/refman/5.5/en/blob.html
And it's usage is as simple as normal string type. But, escaping is required. and query length is must specified because binary data may contain NULL character in their contents.
Before MySQL 3.23 (I guess), There were only mysql_query(), mysql_escape_string(). Those function has no capability specifying query length. after BLOB has been introduced in MySQL, mysql_real_query() and mysql_real_escape_string() supported.
I found some examples for you. May this links help you!
http://zetcode.com/db/mysqlc/
http://bytes.com/topic/c/answers/558973-c-client-load-binary-data-mysql