Difference Between WHERE FIND_IN_SET(...)>0 and WHERE FIND_IN_SET(...) - mysql

According to MySQL Reference Manual - The SET Type
Normally, you search for SET values using the FIND_IN_SET() function or the LIKE operator:
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
According to MySQL Reference Manual
FIND_IN_SET(str,strlist)
Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string list is a string composed of substrings separated by “,” characters. If the first argument is a constant string and the second is a column of type SET, the FIND_IN_SET() function is optimized to use bit arithmetic. Returns 0 if str is not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL.
Therefore, I think that
SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)
works properly when you want to find value from a set.
So why does example from MySQL Reference Manual explicitly comparing with >0 ?
Is there any difference ?

Consider the following two WHERE clauses:
WHERE FIND_IN_SET('value', set_col) > 0
WHERE FIND_IN_SET('value', set_col)
In the first one, if any of the entries in sel_col contains value, then the return value for FIND_IN_SET() will be some number greater than 0, otherwise it will be 0. In other words, it will return TRUE if the value is found, and FALSE otherwise.
The second WHERE clause will evaluate to either WHERE X, where X is either 1 or greater, if value be found, or 0, if value be not found. In MySQL, the value 0 is synonymous with FALSE, and a positive number of 1 or greater is synonymous with TRUE (see documentation).
So these two WHERE clauses will behave identically.

Related

MySQL where condition with only a reference to a column, what does it mean?

Examples:
SELECT *
FROM table t
WHERE t.col1
SELECT *
FROM table t
WHERE t.col1 AND t.col2
Depending the nature of the column these queries behaves differently. In my tests, if the column is of the type integer wont show rows with 0s or nulls for that column, if it string, the query will give no result.
I'd like to understand what these types of where conditions mean. Couldn't find any specification for this in the MySQL manual nor an explanation online.
Thanks.
In your query you are not assigning a valid comparision in the where clause (eg: where t.col1 = 10) .. so the where condtion try to eval a casting for the value in the columns mentioned as boolen
in this case the diffent result is just based on the different casting in boolean of each type
if you firts query based on a integer return always a valid true result so yoi get all the rows in the others with string depending of each string value this can produce no rows ,, partial rows or all rows .. try look at the result for the cast of your column in boolean
SELECT if(t.col1, true, false)
FROM table t
WHERE t.col1
and
SELECT if( t.col1 AND t.col2, true,false)
FROM table t
WHERE t.col1 AND t.col2
Those just aren't proper boolean expressions. Boolean expressions evaluate to either true or false and are of the form where t.col1 = 0 and t.col2 >= 3 for example.
The fact that your statements sometimes return data and sometimes not is due to the fact, that 0 and 1 stands for false and true respectively.
Like you already observed, 0 and NULLs don't return rows because they are treated as false in case of 0 and not comparable in case of NULL. Strings on the other hand are implicitly converted to numbers. If the string starts with a number other than 0, the string is converted to that number in MySQL. If the string starts with anything other than that, it's converted to 0. That's why you don't get results for strings.
I would recommend to not use these "short hand boolean expressions". Always write proper expressions!

SELECT * FROM tableName WHERE 'num+sometext'

I am curious to know , how these queries work in database engine. Specially my focus is on line no 4 and 6.
1.SELECT * FROM tableName
2.SELECT * FROM tableName WHERE 1
3.SELECT * FROM tableName WHERE 123
4.SELECT * FROM tableName WHERE '2xyz'
5.SELECT * FROM tableName WHERE ''
6.SELECT * FROM tableName WHERE 'xyz'
In the above queries 1,2,3,4 are producing same result but 5 and 6 are not producing any result. why? what is diff b/w WHERE '2xyx' and 'xyz'?
How '2xyz' implicitly converted into 2 ?
The where clause evaluates to boolean true (not 0) or false (0) in order to decide if a record is in or out of the resultset.
Cases 2 and 3 retrive all records because the non zero numbers evaluate to true.
Case 3 retrieves all records because during the implicit string to number conversion mysql evaluates the string from left to right character by character. As long as as the characters can be evaluated as a number, mysql will take their value. This includes chopping of leading spaces, interpreting plus or minus signs, decimal points, and so on. So, the string '2xyx' is interpreted as 2, thus boolean true.
Case 4 and 5 do not retrieve any records because the strings' leftmost character cannot be evaluated as a number, so the conversion returns 0, thus boolean false.
Unfortunately, the implicit string to number conversion is not really documented in the MySQL manual. Most of the rules, however, can be deducted from the following part in Type Conversion in Expression Evaluation section of the manual:
For comparisons of a string column with a number, MySQL cannot use an
index on the column to look up the value quickly. If str_col is an
indexed string column, the index cannot be used when performing the
lookup in the following statement:
SELECT * FROM tbl_name WHERE str_col=1;1
The reason for this is that there are many different strings that may
convert to the value 1, such as '1', ' 1', or '1a'.
It is WHERE <condition>, e.g. WHERE col1 = 123. What you have instead is WHERE <number> or WHERE <string>, so there is an expression missing.
What would be possible though is WHERE <boolean>, and this is what MySQL expects. And as MySQL treats booleans like numbers (0 = false, other numbers = true), it looks for a number.
1 and 123 are numbers that result in true.
'2xyz' gets converted to 2, i.e. true.
'' and 'xyz' get converted to 0, i.e. false.
So the latter give you an empty result set as the where condition renders false.
In statement SELECT ... WHERE [where_condition], in where_condition expression you can use any of the functions and operators that MySQL supports, in which string literal is also supported. For strings the comparisons are based on the numeric values of the string unit. When evaluating an expression type conversion is also done.
So in above case the 2xyz gets converted to 2 which is true and hence you get all the records. Its like
SELECT * FROM tableName WHERE 2
and the string xyz gets converted to 0 which is false due to which you get empty result set. Its same as:
SELECT * FROM tableName WHERE 0
Where having condition value. Mysql any number treat as TRUE value and null or '' treat as FALSE.
1.SELECT * FROM tableName -- all record return
2.SELECT * FROM tableName WHERE 1 -- Return true value
3.SELECT * FROM tableName WHERE 123 -- Return true value
4.SELECT * FROM tableName WHERE '2xyz' -- Return true value because there first character is number
5.SELECT * FROM tableName WHERE '' -- false value return
6.SELECT * FROM tableName WHERE 'xyz' -- false value return

Number plus string in MySQL

The expression
SELECT (6000.03 + '00') AS res;
gives the result 6000.03, but the expression
SELECT (6000.00 + '00') AS res;
gives the result 6000. Why is the fractional part discarded in the second expression?
You can't add a string to a number without changing the data type.
MySQL will auto-convert the '00' into a number since you have no explicit date definition in your select.
It will discard the fractional part in the second example as 6000.00 = 6000 = an integer value.
If you do this manipulation in a tables column that is defined as decimal, the fractional part won't be discarded as MySQL won't override your column definitions.

mysql select query gives result where ID (a number) is equal to text

I have a table _users with a field id as bigint(24).
The result of this query:
SELECT * FROM `_users` WHERE `id`='5text'
is the row with id = 5. I would expect no result since '5text' is not a number. How is this possible?
MySQL implicitly converts strings to numbers when evaluates expressions to make the operands compatible.
From the documentation:
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
See the Type Conversion in Expression Evaluation
article for the detailed explanation and examples.

SLEEP(x) role in SQL query clarification

I don't understand the reason why this happens.
Could somebody explain it?
SELECT * FROM users WHERE name = ''
returns 0 records as it should
SELECT * FROM users WHERE name = 'janet'
returns 1 record as it should
SELECT * FROM users WHERE name = ''-SLEEP(3)
returns EVERY record in the table, why??
SLEEP(3) returns 0
using name = ''-0 produces the same result (returning every record)
This is not for practical use it's because I'm testing time-based SQL injections
The documentation for the sleep function states:
Sleeps (pauses) for the number of seconds given by the duration argument, then returns 0. If SLEEP() is interrupted, it returns 1. The duration may have a fractional part.
So it returns an integer, so what you actually have is '' - 0, here '' is implicitly converted to an integer so the two types are comparable, so you then have 0 - 0 which equals 0, so your where clause is actually:
WHERE Name = 0;
Since you are comparing a string with an integer, type conversion must take place. Below is from the MySQL Docs
The following rules describe how conversion occurs for comparison operations:
If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real) numbers.
Since you have one argument that is a string, and one that is an integer it is the final clause that takes place. Converting a string (that is not a number) to a floating point number yields causes an err 0, which you can test using something as simple as:
SELECT CAST('A String' AS DECIMAL(10,5));
Which will give you 0.00000. So your final where clause after conversions have taken place is:
WHERE 0 = 0;
So all rows are returned.
MySQL is truncating the varchar value and is evaluating 0=0 in the Where clause. Execute the query and then execute show warnings; to see that the varchar values are truncated.
MySQL implicit conversions: http://dev.mysql.com/doc/refman/5.5/en/type-conversion.html
In MySQL, SLEEP() is a function that returns 0.
The documentation says it returns 1 when it is interrupted but it does not explain how this behaviour could be achieved. I thinks it's safe to assume it always returns 0 for this discussion.
The WHERE expression name = '' - SLEEP(3) is evaluated as follows:
MySQL calls the SLEEP(3) function; three seconds later it returns the integer value 0;
'' - 0 (the empty string minus zero) is evaluated as a numeric expression (the subtraction operator is not defined for strings); the empty string is converted to number 0, the value of the expression is the number 0 (zero);
the WHERE clause becomes name = 0 where 0 is a number.
The documentation page about Type Conversion in Expression Evaluation contains a list of rules used to convert the values of different types when they are compared:
The following rules describe how conversion occurs for comparison operations:
If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
A single-row subquery from a table or tables is not considered a constant. For example, if a subquery returns an integer to be compared to a DATETIME value, the comparison is done as two integers. The integer is not converted to a temporal value. To compare the operands as DATETIME values, use CAST() to explicitly convert the subquery value to DATETIME.
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real) numbers.
As you can see from this list, the last rule is the one that applies to the WHERE clause name = 0. Both operands are converted to floating point numbers.
Converting a string to an integer or floating point number will produce 0 the string is not the representation of a number.
This is the explanation of the apparently weird behaviour of your query.