Home > database >  SQLite inconsistency behavior with the NOT operator
SQLite inconsistency behavior with the NOT operator

Time:03-20

As for example, I am using this website: https://sqliteonline.com/.

I try to fuzz around with queries and did as such:

SELECT * FROM demo
WHERE Name="SQL " || "Online"

Which correctly retrieved:

1-SQL Online-for Data Science

Now I tried to use the AND operator:

SELECT * FROM demo
WHERE Name="SQL " || "Online" AND Hint=1 IS NOT 2

which retrieved the same answer as before, because 1 is indeed not 2 thus it is Query AND True=>True.

But if I changed it to something else, let's say:

SELECT * FROM demo
WHERE Name="SQL " || "Online" AND Hint=1 IS NOT 1

It returns the same answer as before! even though 1 IS NOT 1 is completely false, as I've seen in this query:

SELECT *, 1 IS NOT 1 AS isTrue FROM demo
WHERE Name="SQL " || "Online" AND Hint=1 IS NOT 1

where isTrue=0

So this query is basically this one:

SELECT *, 1 IS NOT 1 AS isTrue FROM demo
WHERE Name="SQL " || "Online" AND Hint=0

But when I execute this query explicitly, it does not retrieve any results!

What is going on here? I would appreciate your help! Thank you.

CodePudding user response:

According to Operators, and Parse-Affecting Attributes, your condition is equivalent to:

(Name=("SQL " || "Online")) AND ((Hint=1) IS NOT 2)

because of the operators precedence.

This means that it is the boolean expression Hint=1 that is checked whether it is 2 or not.
A boolean expression like Hint=1 is evaluated as 0 for false or 1 for true.

The column Hint's values are strings and prior to the comparison with 1 or any numeric expression SQLite tries to convert them implicitly to numeric values, but since this is not possible they are converted to 0, so, your condition is equivalent to:

(Name=("SQL " || "Online")) AND ((0=1) IS NOT 2)

and since 0=1 evaluates to 0(= false):

(Name=("SQL " || "Online")) AND (0 IS NOT 2)

or:

(Name=("SQL " || "Online")) AND true

or:

Name="SQL " || "Online"

Note that you would get the same result with:

(Name=("SQL " || "Online")) AND ((Hint=1) IS NOT 1)

But, with

(Name=("SQL " || "Online")) AND ((Hint=1) IS NOT 0)

the result would be:

(Name=("SQL " || "Online")) AND false

which evaluates to just false.

  • Related