SELECT id FROM customers WHERE type IS NOT Null;
比较:
SELECT id FROM customers WHERE NOT type IS NULL;
以上两者返回的数据完全相同。
它们有什么区别,并且为什么其中一个更可取?
编辑:
在性能方面可能会有所不同。 有人愿意详细说明吗?
SELECT id FROM customers WHERE type IS NOT Null;
比较:
SELECT id FROM customers WHERE NOT type IS NULL;
以上两者返回的数据完全相同。
它们有什么区别,并且为什么其中一个更可取?
编辑:
在性能方面可能会有所不同。 有人愿意详细说明吗?
没有区别。
对我来说,性能方面可能存在差异。有人可以详细解释一下吗?
所有主要的数据库引擎(包括 MySQL
、SQL Server
、Oracle
和 PostgreSQL
)都会在解析阶段合并这些谓词,并从它们生成相同的查询计划。
处理这些条件比单纯地应用运算符的顺序更为复杂。
例如,在 Oracle
中,IS NOT NULL
(或 NOT IS NULL
)条件意味着可以使用索引,因此像这样的查询:
SELECT column
FROM mytable
WHERE column IS NOT NULL
很可能会使用索引快速全表扫描
执行,而且不会在运行时进行其他检查(因为NULL
值根本进不了索引,所以没有必要检查它们)。
即使需要检查每条记录,检查顺序也将由优化器定义(而不是由谓词和运算符在WHERE
子句中出现的顺序定义)。
例如,这里是一个Oracle
查询的计划:
SQL> EXPLAIN PLAN FOR
2
2 SELECT *
3 FROM t_test
4 WHERE NOT column IS NULL
5 /
Explained
SQL> SELECT *
2 FROM TABLE(DBMS_XPLAN.display())
3 /
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 958699830
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 30 | 1260 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T_TEST | 30 | 1260 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMN" IS NOT NULL)
正如你所看到的,filter
在内部被转换为一个IS NOT NULL
(Oracle
与大多数评论者认为这是一种更合适的形式)。
更新:
正如Jonathan Leffler所指出的,当评估元组(而不是单个列)时存在差异。
一个由混合的NULL
和非NULL
值组成的元组既不是NULL
也不是NOT NULL
。
在PostgreSQL
中(支持对元组使用此谓词),这两个表达式都是:
SELECT (1, NULL) IS NULL
SELECT (1, NULL) IS NOT NULL
计算结果为假。
IS NOT NULL
是一个比较运算符,就像IS NULL
、=
、>
、<
等。
NOT
是一个逻辑运算符,作用于条件的其余部分。因此,您可以说NOT type = 5
、NOT type IS NULL
,甚至是NOT type IS NOT NULL
。
我的观点是要指出,它们是两个非常不同的运算符,尽管结果相同。当然,在布尔逻辑中,NOT (column IS NULL)
和column IS NOT NULL
之间没有区别,但了解差异是明智的。
至于性能,IS NOT NULL
可能会比NOT ... IS NULL
节省一些周期,因为您使用了单个运算符而不是两个运算符,但任何合理的优化器都会在查询运行之前弄清楚它们是相同的。
NOT x IS NULL
和x IS NOT NULL
没有区别。优化器会将这两个相同地处理。<row value predicand>
:
§8.7
<null predicate>
(p395)Specify a test for a null value.
<null predicate> ::= <row value predicand> <null predicate part 2> <null predicate part 2> ::= IS [ NOT ] NULL
追踪语法,您会发现:
§7.2
<row value expression>
(p296)Specify a row value.
[...]
<row value predicand> ::= <row value special case> | <row value constructor predicand> <row value special case> ::= <nonparenthesized value expression primary>
同时:
继续进行。 (通过SQL标准追踪任何内容都是很困难的工作。您可以在http://savage.net.au/SQL/上找到一个大量超链接的标准版本。)§7.1
<row value constructor>
(p293)Specify a value or list of values to be constructed into a row or partial row.
<row value constructor> ::= <common value expression> | <boolean value expression> | <explicit row value constructor>
[...]
<row value constructor predicand> ::= <common value expression> | <boolean predicand> | <explicit row value constructor>
(val1, val2, val3) IS NOT NULL
vs
NOT (val1, val2, val3) IS NULL
现在,在第一种情况下,如果val1、val2和val3都不为NULL,则返回TRUE。在第二种情况下,如果val1、val2或val3中任意一个不为NULL,则返回TRUE。因此,存在两种操作不相同的情况。
然而,正如我之前所说,对于简单列或表达式的通常情况,这两种操作没有区别。
PostgreSQL
中它就是这样工作的。 - QuassnoiSELECT NOT true = ANY(ARRAY[false, false, true]);
与 SELECT true <> ANY(ARRAY[false, false, true]);
。 - Evan Carroll
IS NOT
运算符进行了专利申请(在VB.NET的上下文中,即在SQL之后的几年)。但是很难强制执行这项专利... - Konrad Rudolph