MySql/mariadb - SELECT 0 = 'N;' returns true [duplicate] - php

This question already has answers here:
mysql: why comparing a 'string' to 0 gives true?
(3 answers)
Closed 3 days ago.
I was going through some MySql (mariadb) report looking for why I was getting too many rows in a report and found that the column being queried which stores serialized php and matches another column value is falsely matching.
where m.section = SUBSTRING_INDEX(SUBSTRING_INDEX(s.other,CHAR(59),2),CHAR(58),-1)
This is fine. m.section contains a number. s.other might have a value a:1:{s:3:"foo";i:4;}, so it is matching the 4 in that data.
Then I found that some n.other records are storing null. Php's serialize outputs a capital N followed by a semicolon to represent a null.
echo serialize(null); // outputs N;
echo is_null(unserialize('N;')); // outputs 1
So php thinks N; is null.
In my query, when m.section equals zero, it is matching the record. Zero equals php null? Lets test that.
SELECT 0 = 'N;'
outputs
1 !
What else equals null that shouldn't?
select 1 = 'N;' --> 0
select 0 = null --> null
select 0 is null --> 0
select 'N;' is null --> 0
Am I going mad? How come zero equals php's serial null?

Its not PHP, its MariaDB.
Through the type conversion rules, 'N;' is converted (badly) to DECIMAL.
During the conversion it gets a 0 value. And with the equality test to 0 becomes true.
Looking at the warnings of the select 0 = 'N;' will result in:
Warning 1292 Truncated incorrect DECIMAL value: 'N;'
ref: https://dbfiddle.uk/4rZ0N8CF

Related

While reading an oracle view from php :ORA-06502: PL/SQL: numeric or value error: character to number conversion error

this query it works!
SELECT largdisp FROM vcantieri WHERE SEQ_EVENTO=97161
(value of largdisp is 600 and it works for any value 500,600,700...1000 or null)
this query gives an ERROR! ORA-06502
SELECT largdisp FROM vcantieri WHERE SEQ_EVENTO=97195
(value of largdisp 650 and not works for any value 750,850,950....)
largdisp is a decimal field in original table, converted in varchar2 in view
IN TOAD this query it works always!!!

MySQL updates all rows when the column name is only specified in the where clause

It's been a while I didn't work on mysql and I was suprised to see that the following statement is valid:
UPDATE table_A
SET col_a = value
WHERE id;
It looks like MySQL updates all rows in the table. I have a good MSSQL background and I am trying to understand why this valid in MySql?
Also, I ran a query with a similar where clause on a varchar column:
SELECT distinct description
FROM table_A
where NOT description;
I tought it will return only null or empty values. Instead, it returns lots of rows with non-null values.
Any ideas why?
Thanks,
WHERE x will match any rows for which x evaluates to a truthy value. Since BOOLEAN is actually a number type TINYINT(1), this works by converting to a number and then comparing to zero - any nonzero number is truthy. (NULL is falsy.)
If you write WHERE id = 123, then only for the row where id is 123, the expression id = 123 will evaluate to TRUE (which is the same as 1) and it will match, otherwise it will evaluate to FALSE (0).
But if you write WHERE id, the requirement is that id evaluates to a truthy value. If id is a number, only IDs 0 and NULL will be falsy.
However, in case of description, you have a string. And the string is first converted to a number. The reason you got many results there is that any string that starts with a number (that is nonzero) is matching, such as 01234hello (which converts to 1234, which is nonzero). Check what CONVERT(description, SIGNED) gives - if it is nonzero, then it matches.
This is why, when building AND or OR queries in code, you can avoid handling the case of zero conditions specially by starting with TRUE or 1 (in the AND case) or FALSE or 0 (in the OR case), since WHERE TRUE/WHERE 1 is valid (matches everything), as is WHERE FALSE/WHERE 0 (matches nothing). So you build a query by starting with WHERE 1 and adding to it: WHERE 1, WHERE 1 AND id = 123, WHERE 1 AND id = 123 AND type = 'xy', etc.

Return BLOB column Which is Empty Or Not Empty as 1 or 0

I have a table with BLOB column that some row has BLOB, some empty.
1 Apple BLOB-8KiB
2 Banana
3 Pear BLOB-6KiB
4 Orange BLOB-7KiB
Is there any way I can use PHP MYSQL to get the array like this:
$fruit = array(
array("1",Apple,1),
array("2",Banana,0),
array("3",Pear,1),
array("4",Orange,1)
);
I just want to change the BLOB data with 1, Empty with 0 in my PHP array. Pls help.
Your select statement can use IF and ISNULL (note these are not widely implemented in the same format on different database backends, this is for MySQL).
So you would use:
SELECT ID, Name, IF(ISNULL(BlobField), 0, 1) FROM TableName
IF allows you to choose one of two values according to a logical operation.
ISNULL returns true or false according to whether or not the value is NULL

What is the max size of type "SQLITE3_INTEGER"?

As mentioned in https://www.sqlite.org/datatype3.html :
INTEGER: The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8
bytes depending on the magnitude of the value.
The problem is that the statement below gives the desired result as the bound values are comparatively smaller (e.g, $roll_no = 1111111111), however, the execution of statement fetches no result when the bound value is bigger(e.g, $roll_no =3333333333) whereas the SQLite table already holds record with that bigger value.
Is it because the parameter value is truncated or any other reason? What is to be done to get rid of it?
$stmt1 = $db->prepare("select sname,reg_no from student where roll_no=:roll_no");
$stmt1->bindParam(':roll_no', $roll_no, SQLITE3_INTEGER);
See the PDO driver of PHP:
https://github.com/php/php-src/search?q=SQLITE_INTEGER&unscoped_q=SQLITE_INTEGER
#if LONG_MAX <= 2147483647
if (val > ZEND_LONG_MAX || val < ZEND_LONG_MIN) {
ZVAL_STRINGL(data, (char *)sqlite3_column_text(stmt, column), sqlite3_column_bytes(stmt, column));
It supports returning larger integers, but only as strings.
There's no way to have 3333333333 as native integer on PHPs end (32-bit versions). Such it would become a float before it even reaches SQLite.
What you should do is not trying to bind it as integer. Use a string. SQL does type casting of its own. You could likely keep the column as INTEGER on SQLites end even. It's only PHP you have to work around. Or you know, do the overdue upgrade.

SQL SELECT is selecting rows that do not match the query

I am using php mysql_query() to select rows from my SQL Database but for some reason it is selecting rows that do not match the query. For example:
mysql_query("SELECT * FROM Table WHERE ID='153'")
This will return the row who has an ID of 153
but so will:
mysql_query("SELECT * FROM Table WHERE ID='153c'")
Am I doing something wrong?
As noted, the issue is comparing a string value to an integer value. Your expression is:
WHERE ID = '153' and
WHERE ID = '153a'
You can imagine the MySQL engine describing what it does as: "id is an integer column. So, I need to compare it to an integer value. Oh, the right side is a string, so I will convert the right hand side to an integer."
The way that MySQL converts values to a number from a string could be called "silent conversion". It converts the longest leading number that it finds, and then stops. If there is no leading number (say 'a123'), then the value is 0. There is no error produced.
If you really want to confuse yourself, consider the following:
select (case when 123 = '123e' then 1 else 0 end),
(case when 123 = '123e3' then 1 else 0 end),
(case when 123 = '123a' then 1 else 0 end),
(case when 123 = '123a3' then 1 else 0 end)
This returns: true, false, true, and true. Why is the second one false, but the others true? Well, '123e3' is interpreted as scientific notation, so the value becomes 123,000. For all the others, the conversion stops at the first alphabetic character.
As mentioned in the other answers, the obvious fix is to drop the single quotes on the constant.
Why are you passing the ID value as a String? This would most likely be your issue. Try passing the following query instead:
mysql_query("SELECT * FROM Table WHERE ID= 153")
This way, the ID value being searched for is an int (or any other primitive the ID column is set to). This should restrict the IDs properly. In addition, if you are creating IDs with numbers, it's best practice to use distinct ints only and not strings.

Categories