布尔值之间的 SQL less/greater 比较会产生意外结果

smi*_*hax 5 mysql sql sqlite postgresql mariadb

为什么大多数(全部?)SQL 数据库给出:

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??
Run Code Online (Sandbox Code Playgroud)

只需仔细检查即可:

SELECT NOT(TRUE) = FALSE;  -- TRUE / 1    Ok
SELECT NOT(FALSE) = TRUE;  -- TRUE / 1    Ok
Run Code Online (Sandbox Code Playgroud)

在 Postgres 中,我还可以检查:

SELECT pg_typeof(TRUE), pg_typeof(NOT(FALSE));
  -- boolean | boolean
Run Code Online (Sandbox Code Playgroud)

我已经在 PostgreSQL、SQLite3 和 MariaDB 上尝试过这一点,并且都同意相同的意外结果。
我缺少什么?

Laj*_*pad 8

NOT<是运营商。让我们看一下运算符优先级:

在此输入图像描述

https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html

从这里我们可以看到<优先级NOT优先,所以

NOT(FALSE) < FALSE
Run Code Online (Sandbox Code Playgroud)

相当于

NOT(FALSE < FALSE)
Run Code Online (Sandbox Code Playgroud)

自从FALSE不小于自身,因此内部表达式为 0,即 it'sFALSE且其否定为TRUE

然而,如果您强制执行您希望的操作员命令:

(NOT(FALSE)) < FALSE
Run Code Online (Sandbox Code Playgroud)

然后你会得到你期望的结果:

在此输入图像描述


Tim*_*sen 6

我不知道具体NOT(FALSE)是如何评估的,但NOT它不是一个函数。如果您不想使用布尔文字,那么括号应该放在整个表达式周围,即使用(NOT FALSE)而不是NOT(FALSE)。考虑:

SELECT (NOT FALSE) < FALSE; -- 0, same as TRUE < FALSE
SELECT (NOT TRUE) < FALSE;  -- 0, same as FALSE < FALSE
Run Code Online (Sandbox Code Playgroud)


for*_*pas 5

我的答案是关于 SQLite (但我怀疑这同样适用于其他数据库)。

像这样的表达式:

NOT(FALSE) < FALSE;
Run Code Online (Sandbox Code Playgroud)

被评估为:

NOT((FALSE) < FALSE);
Run Code Online (Sandbox Code Playgroud)

因为运算符 的<优先级高于 运算符NOT
由于(FALSE) < FALSE计算结果为FALSE,因此表达式的结果为TRUE