为什么 'WHERE NOT' 的 NULL 行不起作用?
Why isn't 'WHERE NOT' with NULL-rows working?
也许我只是漏掉了什么。由于问题太不具体,无法 google 它/搜索它,我现在在这里寻求帮助。在 MySQL
中测试
我的问题:为什么这个SELECT不输出[id=2]?
SELECT `id` FROM `testtable1` WHERE NOT (`key_boolean` = 1);
Table 定义和测试数据:
CREATE TABLE IF NOT EXISTS `testtable1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key_boolean` tinyint NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) AUTO_INCREMENT=1;
INSERT INTO `testtable1` (`key_boolean`) VALUES (1);
INSERT INTO `testtable1` () VALUES ();
中table现存:
id
key_boolean
1
1
2
NULL
编辑:
根据答案,我实际上在 Whosebug 上发现了一些类似的问题。这个 post 很适合 MySQL: MYSQL syntax not evaluating not equal to in presence of NULL
NULL 在概念上意味着不确定。所以 NOT NULL 也是 NULL,而且是假的。如果要包含 NULL,可以测试 CASE WHEN key_boolean=1 THEN 0 ELSE 1 END
。
当 key_boolean
为 NULL
时,表达式 key_boolean = 1
的计算结果为 NULL
。所以你中间有 NOT NULL
for NOT (key_boolean = 1)
。 NOT NULL
反过来也计算为 NULL
。由于 NULL
不是真的(但也不是假的——在 SQL 中应用 ternary logic),该行不是 selected.
除少数情况外,所有比较运算,如 =
,如果其中一个操作数是 NULL
,则计算结果为 NULL
。 MySQL 中的一个没有 table 异常,在这种情况下,是 NULL
-safe equal <=>
,它的行为就像您想要的那样。
您可以 select 测试中的(子)表达式 table 并亲自查看它们的结果。
SELECT *,
key_boolean = 1,
NOT (key_boolean = 1),
key_boolean <=> 1,
NOT (key_boolean <=> 1)
FROM testtable1;
就我个人而言,我发现@sticky-bit 和@ysth 的回答非常有帮助,但我想分享一些关于我的研究的更多信息:
结论:
SQL 遵循三值逻辑 (3VL)。这意味着除了 TRUE(1) 和 FALSE(0) 之外还有 NULL。这意味着如果比较中的操作数之一为 NULL,则结果也为 NULL。另请参阅维基百科上的真相 table:https://en.wikipedia.org/wiki/Null_(SQL)#Comparisons_with_NULL_and_the_three-valued_logic_(3VL)
没有NOT的例子1:
SELECT id FROM testtable1 WHERE (key_boolean = 1);
, 所以:
- [第 1 行]
key_boolean
= 1 --> 1 = 1 --> 真
- [第 2 行]
key_boolean
= 1 --> NULL = 1 --> NULL
-> 所以,第 1 行是 selected.
例2,和例1一样,只是求反,所以with NOT:
SELECT id FROM testtable1 WHERE NOT (key_boolean = 1);
,所以
- [第 1 行] NOT (
key_boolean
) = 1 --> 1 = 1 --> TRUE
- [第 2 行] NOT (
key_boolean
) = 1 --> NULL = 1 --> NULL
-> 空结果。
问题解决方案:
正如@sticky-bit 已经写的那样,MySQL中有NULL-safe equal,在这个例子中也达到了预期的效果。
<=> 不幸的是,它只适用于 MySQL(然后也适用于 MariaDB)。我在 https://modern-sql.com/feature/is-distinct-from 找到了不同方言的比较。 @ysth 关于“CASE WHEN”的建议可能适用于所有方言,但会爆炸 select-terms.
在我的具体情况下(不再是实际问题的一部分)我现在用 COALESCE()
解决了它 - 确定了 NULL 值的默认值,因为在我的情况下,我不仅必须支持 mysql,参见:
SELECT `id` FROM `testtable1` WHERE NOT (COALESCE(`key_boolean`, 0) = 1);
进一步阅读:
如果像我一样从未听说过 NULL 安全等于运算符 <=>,请参阅:What is this operator <=> in MySQL?
现在我绝不是数据库技术人员,但知道 NULL 是未定义的(来自其他编程语言)。对我来说,一个明显的问题是为什么至少 SQL 不每次都使用 NULL-safe equal。请参阅:Is there a reason not to use <=> (null safe equals operator) in mysql instead of =? and Is there a reason not to use <=> (null safe equals operator) in mysql instead of =? [每个都带有标记 post]。
也许我只是漏掉了什么。由于问题太不具体,无法 google 它/搜索它,我现在在这里寻求帮助。在 MySQL
中测试我的问题:为什么这个SELECT不输出[id=2]?
SELECT `id` FROM `testtable1` WHERE NOT (`key_boolean` = 1);
Table 定义和测试数据:
CREATE TABLE IF NOT EXISTS `testtable1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key_boolean` tinyint NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) AUTO_INCREMENT=1;
INSERT INTO `testtable1` (`key_boolean`) VALUES (1);
INSERT INTO `testtable1` () VALUES ();
中table现存:
id | key_boolean |
---|---|
1 | 1 |
2 | NULL |
编辑: 根据答案,我实际上在 Whosebug 上发现了一些类似的问题。这个 post 很适合 MySQL: MYSQL syntax not evaluating not equal to in presence of NULL
NULL 在概念上意味着不确定。所以 NOT NULL 也是 NULL,而且是假的。如果要包含 NULL,可以测试 CASE WHEN key_boolean=1 THEN 0 ELSE 1 END
。
当 key_boolean
为 NULL
时,表达式 key_boolean = 1
的计算结果为 NULL
。所以你中间有 NOT NULL
for NOT (key_boolean = 1)
。 NOT NULL
反过来也计算为 NULL
。由于 NULL
不是真的(但也不是假的——在 SQL 中应用 ternary logic),该行不是 selected.
除少数情况外,所有比较运算,如 =
,如果其中一个操作数是 NULL
,则计算结果为 NULL
。 MySQL 中的一个没有 table 异常,在这种情况下,是 NULL
-safe equal <=>
,它的行为就像您想要的那样。
您可以 select 测试中的(子)表达式 table 并亲自查看它们的结果。
SELECT *,
key_boolean = 1,
NOT (key_boolean = 1),
key_boolean <=> 1,
NOT (key_boolean <=> 1)
FROM testtable1;
就我个人而言,我发现@sticky-bit 和@ysth 的回答非常有帮助,但我想分享一些关于我的研究的更多信息:
结论: SQL 遵循三值逻辑 (3VL)。这意味着除了 TRUE(1) 和 FALSE(0) 之外还有 NULL。这意味着如果比较中的操作数之一为 NULL,则结果也为 NULL。另请参阅维基百科上的真相 table:https://en.wikipedia.org/wiki/Null_(SQL)#Comparisons_with_NULL_and_the_three-valued_logic_(3VL)
没有NOT的例子1:
SELECT id FROM testtable1 WHERE (key_boolean = 1);
, 所以:
- [第 1 行]
key_boolean
= 1 --> 1 = 1 --> 真 - [第 2 行]
key_boolean
= 1 --> NULL = 1 --> NULL
-> 所以,第 1 行是 selected.
例2,和例1一样,只是求反,所以with NOT:
SELECT id FROM testtable1 WHERE NOT (key_boolean = 1);
,所以
- [第 1 行] NOT (
key_boolean
) = 1 --> 1 = 1 --> TRUE - [第 2 行] NOT (
key_boolean
) = 1 --> NULL = 1 --> NULL
-> 空结果。
问题解决方案:
正如@sticky-bit 已经写的那样,MySQL中有NULL-safe equal,在这个例子中也达到了预期的效果。 <=> 不幸的是,它只适用于 MySQL(然后也适用于 MariaDB)。我在 https://modern-sql.com/feature/is-distinct-from 找到了不同方言的比较。 @ysth 关于“CASE WHEN”的建议可能适用于所有方言,但会爆炸 select-terms.
在我的具体情况下(不再是实际问题的一部分)我现在用 COALESCE()
解决了它 - 确定了 NULL 值的默认值,因为在我的情况下,我不仅必须支持 mysql,参见:
SELECT `id` FROM `testtable1` WHERE NOT (COALESCE(`key_boolean`, 0) = 1);
进一步阅读: 如果像我一样从未听说过 NULL 安全等于运算符 <=>,请参阅:What is this operator <=> in MySQL?
现在我绝不是数据库技术人员,但知道 NULL 是未定义的(来自其他编程语言)。对我来说,一个明显的问题是为什么至少 SQL 不每次都使用 NULL-safe equal。请参阅:Is there a reason not to use <=> (null safe equals operator) in mysql instead of =? and Is there a reason not to use <=> (null safe equals operator) in mysql instead of =? [每个都带有标记 post]。