Mysql gives me unrelated results - mysql

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.

Related

SQL ignoring string in where condition

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

SQL converts 'a' to 0 on a integer column. Can i prevent this?

SQL converts a string ('a') to integer (0) on a integer column as learned before in:
Why does SELECT ... WHERE id = a returns a result if value is 0
Is there a way to prevent this? For example: SELECT ... WHERE id = NO_CONVERT_STR('a') or something like this? I don't want to change the data type of the id column
I tried the CAST('a' AS CHAR) method without luck
MySQL has an option for turning off such conversions on inserts. I don't believe there is an option to turn off silent conversion.
You can, however, force an error by doing an explicit conversion:
where id = convert('a' as unsigned)
This should generate an error.

Automatic MySQL data type casting

I just happened upon an interesting case of data type casting in MySQL. Consider the following queries:
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col=123; #Yields 0 rows
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="123"; #Yields 0 rows
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="0"; #Yields 1 row, col=0
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="abc"; #Yields 1 row, col=0
Lines 1, 2, and 3 seem logical to me. But on line 4, why, oh why, dear SQL, do you so eagerly cast "abc" to be equal to 0?!
I mean, I get it - "abc" isn't an integer, so 0 makes the most sense... Is there a scenario in which this behavior is actually useful? As far as I can tell, it likely just leads to bugs (as it did on our application)...
Perhaps there's a MySQL "mode" that enables warnings for automatic type-casting like this?
MySQL does implicit type casting for strings in a numeric context. The leading numeric characters of the string are converted to a number, so a string such as 'abc' gets converted to 0.
This can be very handy because this conversion does not cause an error (an explicit conversion would).
The moral is simple: When comparing constants to columns, make the column the same type as the column. That is, don't compare strings and numbers, lest something unexpected happen.
This is definitely the way MySQL works.
When you use a comparison that compares a numeric object to a string constant, the string gets cast as an integer. MySQL tries to interpret the string as an number, like this:
'0123abc' gets the value 123.
'1abc' gets the value 1.
'abc' gets the value 0.
What use is this? It comes in handy in ORDER BY clauses if you need numeric text strings ordered in numeric order with '112abc' after '12abc'.

What is the difference between = and LIKE

I am running a query on a column postal (type double).
SELECT * FROM `table` WHERE `postal` LIKE 'abcdef'; # returns 1 record
and the same query using = returns 100+ records.
SELECT * FROM `table` WHERE `postal` = 'abcdef'; # returns 107 record
What could be the reason?
You are using LIKE on a DOUBLE field, you should not do that.
LIKE is reserved for pattern matching on strings. Use = for numbers, or convert your digit to a string first using CONVERT and then apply the logic with LIKE.
= compares two values for identity.
LIKE is for pattern matching ie. that is, it matches a string value against a pattern string containing wild-card characters.
Refer here
LIKE will check and return similar values where as = will check for the exact value.
The following things affects the result (not the complete list!)
Implicit conversation
MySQL extension to standard SQL's LIKE operator
In each cases an implicit conversion occours: MySQL tries to convert the values to a common data type. In the first case case 'abcdef' will be converted to double which results to 0. This is why you get 107 records when comparing with equals (=).
SELECT * FROM `table` WHERE `postal` = 'abcdef'; # returns 107 record
You should get exactly the same result by running
SELECT * FROM `table` WHERE `postal` = 0;
In MySQL, LIKE is permitted on numeric expressions. (This is an extension to the standard SQL LIKE.)
This means that SELECT CASE WHEN 10 LIKE '1%' THEN 1 ELSE 0 END is allowed and results to 1 (matched)
To be honest, I'm not sure which double value could match with LIKE operator with the pattern 'abcdef'.

MySQL In clause not giving the right result

In a MySQL table i have a field, containing this value for a given record : "1908,2315,2316"
Here is my sql Query :
SELECT * FROM mytable WHERE 2316 IN (myfield)
I got 0 results!
I tried this :
SELECT * FROM mytable WHERE 2315 IN (myfield)
Still 0 results
And then i tried this :
SELECT * FROM mytable WHERE 1908 IN (myfield)
Surprisingly i obtained the record when searching with 1908! What should i do to also obtain the record when searching with 2315 and 2316 ? What am i missing ?
Thanks
You appear to be storing comma delimited values in a field. This is bad, bad, bad. You should be using a junction table, with one row per value.
But, sometimes you are stuck with data in a particular structure. If so, MySQL provides the find_in_set() functions.
SELECT *
FROM mytable
WHERE find_in_set(2316, myfield) > 0;
You can't use IN() over comma separated list of no.s its better to normalize your structure first for now you can use find_in_set to find results matching with comma separated string
SELECT * FROM mytable WHERE find_in_set('1908',myfield) > 0
This question has been asked and answered before, but I don't want to hunt for it; this question should be closed as a duplicate. But, to answer your question:
The commas in the string, the column value, are just characters. Those are part of the string. They aren't seen as "separators" between values in the SQL text. The way SQL sees it, the column contains a single value, not a "list" of values.
So, in your query, the IN (field) is equivalent to an equals comparison. It's equivalent to comparing to a string. For example:
... WHERE 2316 = '1908,2315,2316'
And those aren't equal, so the row isn't returned. The "surprisingly" finding of a match, in the case of:
... WHERE 1908 IN ('1908,2315,2316')
that's explained because that string is being evaluated in a numeric context. That is, the comparison returns true, because all of these also true:
... WHERE 1908 = '1908,2315,2316' + 0
... WHERE 1908 = '1908xyz' + 0
... WHERE 1908 = '1907qrs' + 1
(When evaluated in a numeric context, a string gets converted to numeric. It just happens that the string evaluates to a numeric value that equals the integer value it's being comparing to.)
You may be able to make use of the MySQL FIND_IN_SET function. For example:
... WHERE FIND_IN_SET(2316,'1908,2315,2316')
But, please seriously reconsider the design of storing comma separated list. I recommend Bill Karwin's "SQL Antipatterns" book...
http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557
In mysql IN clause is utilized as
SELECT * FROM mytable WHERE column_name IN (set_of_values) ;
Mention column name instead of values
Please try
SELECT * FROM mytable WHERE LOCATE(CONCAT (',', 2316 ','), CONCAT (',',myfield,',' ) ) <>0