为什么 SQL 最终将 NULL 值视为 FALSE?
Why SQL does finally treat a NULL value as FALSE?
因为 NULL
它只是一个未知值或缺失值,所以可能是 TRUE
但我们不知道。为什么FALSE
推定?除了 "it's obvious" 之外,它是否有任何理由(因为它不是)或者应该被视为一种 SQL 糟糕的设计工件?
例如:
SELECT * FROM `rainbow_table` WHERE `show_me`
有些行为空 show_me
。我们真的不知道是否应该输出这样的行,也许最好显示它(作为防止数据丢失的最后机会)?好像SQL是悲观主义者开发的
SQL 并没有真正将 NULL
视为假。相反,只有当条件计算结果为真时,条件语句才被视为真。
效果是NULL
被当成false。但这并不意味着NULL
等同于false。
在SQL中,NULL表示它有一些值,但我们不知道它是什么。这就是为什么我们比较时会这样使用
Select * from table [table name] where [column name] is not NULL
问题是 Sql Server
引擎是建立在三值谓词逻辑之上的。如果谓词比较 2 个非空值,那么它可以被评估为 TRUE
或 FALSE
。如果 then 中至少有一个是 NULL
,则 predicate 的计算结果为第三个逻辑值 - UNKNOWN
.
现在 WHERE
子句中发生了什么?它的设计方式是 returns 行,其中谓词的计算结果仅为 TRUE
!如果谓词的计算结果为 FALSE
或 UNKNOWN
,则相应的行会从结果集中过滤掉。
起初这非常令人困惑,并且会导致新手进入 SQL
的世界时犯几个典型的错误。他们只是不认为数据可能包含 NULL
s。例如,其中一个经典错误是:
Employyes(Name varchar, Contry varchar)
'John', 'USA'
'Peter', NULL
'Mike', 'England'
并且您想要 Contry
不是 USA
的所有行。你只需写:
select * from Employees where Country <> 'USA'
并且只得到:
'Mike', 'England'
结果。乍一看这很令人困惑,但据您了解引擎正在执行三值逻辑,结果是合乎逻辑的。
在 SELECT
语句的上下文中(因此,在 ON
子句、WHERE
子句和 CASE
表达式中),谓词必须是 TRUE
(不是 FALSE
或 UNKNOWN
1)要满足的谓词。
但是,在 CHECK
限制条件下,谓词不能 FALSE
才能得到满足。
即以下脚本将起作用:
CREATE TABLE T (
ID int not null,
Val varchar(10) null,
constraint CK_Vals CHECK (Val in ('abc','def'))
);
INSERT INTO T(ID,Val) VALUES (10,NULL);
因此我们可以看出,在 SQL 中 UNKNOWN
结果被视为 FALSE
并非 普遍 正确。用 NOT (<existing predicate>)
包装产生 UNKNOWN
的谓词不会产生 TRUE
.
的事实也证明了这一点。
Three-Valued logic 上的维基百科页面涵盖了很多细节。
1我假设你的问题是关于 UNKNOWN
而不是 NULL
,因为你已经标记 sql and relational-algebra. In standard SQL, UNKNOWN
and NULL
are two distinctly different concepts. Only (so far as I'm aware) mysql 将两者混为一谈.
因为 NULL
它只是一个未知值或缺失值,所以可能是 TRUE
但我们不知道。为什么FALSE
推定?除了 "it's obvious" 之外,它是否有任何理由(因为它不是)或者应该被视为一种 SQL 糟糕的设计工件?
例如:
SELECT * FROM `rainbow_table` WHERE `show_me`
有些行为空 show_me
。我们真的不知道是否应该输出这样的行,也许最好显示它(作为防止数据丢失的最后机会)?好像SQL是悲观主义者开发的
SQL 并没有真正将 NULL
视为假。相反,只有当条件计算结果为真时,条件语句才被视为真。
效果是NULL
被当成false。但这并不意味着NULL
等同于false。
在SQL中,NULL表示它有一些值,但我们不知道它是什么。这就是为什么我们比较时会这样使用
Select * from table [table name] where [column name] is not NULL
问题是 Sql Server
引擎是建立在三值谓词逻辑之上的。如果谓词比较 2 个非空值,那么它可以被评估为 TRUE
或 FALSE
。如果 then 中至少有一个是 NULL
,则 predicate 的计算结果为第三个逻辑值 - UNKNOWN
.
现在 WHERE
子句中发生了什么?它的设计方式是 returns 行,其中谓词的计算结果仅为 TRUE
!如果谓词的计算结果为 FALSE
或 UNKNOWN
,则相应的行会从结果集中过滤掉。
起初这非常令人困惑,并且会导致新手进入 SQL
的世界时犯几个典型的错误。他们只是不认为数据可能包含 NULL
s。例如,其中一个经典错误是:
Employyes(Name varchar, Contry varchar)
'John', 'USA'
'Peter', NULL
'Mike', 'England'
并且您想要 Contry
不是 USA
的所有行。你只需写:
select * from Employees where Country <> 'USA'
并且只得到:
'Mike', 'England'
结果。乍一看这很令人困惑,但据您了解引擎正在执行三值逻辑,结果是合乎逻辑的。
在 SELECT
语句的上下文中(因此,在 ON
子句、WHERE
子句和 CASE
表达式中),谓词必须是 TRUE
(不是 FALSE
或 UNKNOWN
1)要满足的谓词。
但是,在 CHECK
限制条件下,谓词不能 FALSE
才能得到满足。
即以下脚本将起作用:
CREATE TABLE T (
ID int not null,
Val varchar(10) null,
constraint CK_Vals CHECK (Val in ('abc','def'))
);
INSERT INTO T(ID,Val) VALUES (10,NULL);
因此我们可以看出,在 SQL 中 UNKNOWN
结果被视为 FALSE
并非 普遍 正确。用 NOT (<existing predicate>)
包装产生 UNKNOWN
的谓词不会产生 TRUE
.
Three-Valued logic 上的维基百科页面涵盖了很多细节。
1我假设你的问题是关于 UNKNOWN
而不是 NULL
,因为你已经标记 sql and relational-algebra. In standard SQL, UNKNOWN
and NULL
are two distinctly different concepts. Only (so far as I'm aware) mysql 将两者混为一谈.