“Is Not Null”和“Not Is Null”之间的区别是什么?

时间:2010-11-01 15:17:06

标签: sql mysql sql-server

SELECT id FROM customers WHERE type IS NOT Null;

对战:

SELECT id FROM customers WHERE NOT type IS NULL;

上述任何一项返回的数据都将完全相同。

有什么区别,为什么其中一个会更好?

修改
在我看来,在性能方面可能会有所不同。有人关心这个吗?

3 个答案:

答案 0 :(得分:32)

没有区别。

  

在我看来,在性能方面可能会有所不同。有人关心这个吗?

所有主要引擎(MySQLSQL ServerOraclePostgreSQL)都会在解析阶段合并这些谓词,从而制定相同的计划。

仅仅按照一个或另一个顺序应用操作员,处理这些条件就更复杂了。

例如,在Oracle中,IS NOT NULL(或NOT IS NULL)条件意味着可以使用索引,因此像这样的查询:

SELECT  column
FROM    mytable
WHERE   column IS NOT NULL

很可能会使用index fast full scan执行,而不会在运行时进行额外的检查(因为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 NULLOracle以及大多数评论者似乎认为这是更合适的形式)

<强>更新

正如Jonathan Leffler指出的那样,在评估元组时(而不是单列),这些是不同的。

由混合NULL和非NULL值组成的元组既不是NULL也不是NOT NULL

PostgreSQL(支持这个针对元组的谓词)中,这两个表达式都是:

SELECT  (1, NULL) IS NULL
SELECT  (1, NULL) IS NOT NULL

评估为假。

答案 1 :(得分:15)

IS NOT NULLcomparison operator,就像IS NULL=><等。

NOT是一个logical operator,可以对其他条件采取行动。因此,您可以说NOT type = 5NOT type IS NULL,甚至NOT type IS NOT NULL

我的观点是指出它们是两个非常不同的运算符,即使结果是相同的。当然,在布尔逻辑中,NOT (column IS NULL)column IS NOT NULL之间没有区别,但知道差异是明智的。

至于性能,IS NOT NULL可能会比NOT ... IS NULL节省几个周期,因为您使用的是单个运算符而不是两个运算符,但任何合理的优化器都会发现它们在使用之前是相同的查询已运行。

答案 2 :(得分:12)

在LHS术语是简单变量或表达式的通常情况下,NOT x IS NULLx IS NOT NULL之间没有区别。优化器会以相同的方式对待这两者。

但是,在完整的SQL中,LHS术语不仅限于简单的变量或表达式;在形式语法中,LHS是<row value predicand>

SQL / Foundation - ISO / IEC 9075-2:2003

  

§8.7<null predicate>(p395)

     

指定空值的测试。

<null predicate> ::= <row value predicand> <null predicate part 2>

<null predicate part 2> ::= IS [ NOT ] NULL

追逐语法,你会发现:

  

§7.2<row value expression>(p296)

     

指定行值。

     

[...]

<row value predicand>  ::=
       <row value special case>
 |     <row value constructor predicand>

<row value special case> ::= <nonparenthesized value expression primary> 

  

§7.1<row value constructor>(p293)

     

指定要构造为行或部分行的值或值列表。

<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>

所以它继续下去。 (通过SQL标准追逐任何内容都很难。您可以在http://savage.net.au/SQL/找到标准的重载超链接版本。)

但是,正如您在提到“行值”时可能猜到的那样,您可以在LHS上组合多个简单表达式以形成“行值构造函数谓词”。然后两种形式之间存在差异。

从概念上讲,你有:

(val1, val2, val3) IS NOT NULL

VS

NOT (val1, val2, val3) IS NULL

现在,在第一种情况下,如果val1,val2和val3中的每一个都不为NULL,则为TRUE。在第二种情况下,如果val1,val2,val3中的任何一个不为NULL,则为TRUE。因此,在某些情况下,这两种操作并不相同。

但是,正如我前面所说,对于简单的列或表达式的通常情况,两者之间没有区别。