Why do most(all?) SQL Databases give:
SELECT FALSE < FALSE; -- FALSE / 0 Ok
SELECT TRUE < FALSE; -- FALSE / 0 Ok
SELECT NOT(FALSE) < FALSE; -- TRUE / 1 What?
SELECT NOT(TRUE) < FALSE; -- TRUE / 1 What??
And just do double check:
SELECT NOT(TRUE) = FALSE; -- TRUE / 1 Ok
SELECT NOT(FALSE) = TRUE; -- TRUE / 1 Ok
In Postgres, I can also check:
SELECT pg_typeof(TRUE), pg_typeof(NOT(FALSE));
-- boolean | boolean
I’ve tried this with PostgreSQL, SQLite3 and MariaDB, and all agree on the same unexpected result.
What am I missing?
3
Answers
I don’t know exactly how
NOT(FALSE)
is evaluating, butNOT
is not a function. If you want to not a boolean literal, then the parentheses should be around the entire expression, i.e. use(NOT FALSE)
instead ofNOT(FALSE)
. Consider:NOT
and<
are operators. Let’s take a look at operator precedence:https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html
From here we can see that
<
precedesNOT
in priority, sois equivalent to
and since
FALSE
is not smaller than itself, the inner expression is 0, that is, it’sFALSE
and its negation is true.Whereas, if you enforce the operator order you preferred:
then you will get the result you expected:
My answer is about SQLite (but I suspect that the same applies to other dbs).
An expression like:
is evaluated as:
because the operator
<
has higher precedence over the operatorNOT
.Since
(FALSE) < FALSE
evaluates toFALSE
, the result of the expression isTRUE
.