Подтвердить что ты не робот

В чем разница между "Не является нулевым" и "Не является нулевым",

SELECT id FROM customers WHERE type IS NOT Null;

Versus:

SELECT id FROM customers WHERE NOT type IS NULL;

Данные, возвращаемые одним из вышеперечисленных, будут точно такими же.

В чем разница и почему один из них предпочтительнее?

Edit:
Мне кажется, что может быть разница в производительности. Кто-нибудь позаботится об этом?

4b9b3361

Ответ 1

Нет никакой разницы.

Мне кажется, что может быть разница, когда дело доходит до производительности. Кто-нибудь позаботится об этом?

Все основные двигатели (т.е. MySQL, SQL Server, Oracle и PostgreSQL) объединит эти предикаты на этапе синтаксического анализа, сделав из них одинаковые планы.

Обработка этих условий более сложна, просто применяя операторы в том или ином порядке.

Например, в 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 NULL (который Oracle, как и большинство комментаторов, кажется, является более подходящей формой)

Update:

Как отметил Джонатан Леффлер, это разница при оценке кортежей (в отличие от отдельных столбцов).

Кортеж, состоящий из смешанных значений NULL и non NULL, не является ни a NULL, ни a NOT NULL.

В PostgreSQL (который поддерживает этот предикат против кортежей), оба этих выражения:

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

оценивается как false.

Ответ 2

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, потому что вы используете один оператор вместо двух операторов, но любой разумный оптимизатор выяснит, что это то же самое, что и до запуска запроса.

Ответ 3

В обычном случае, когда член LHS является простой переменной или выражением, между NOT x IS NULL и x 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, чтобы сформировать "predicand конструктора значений строки". И тогда есть разница между двумя формами.

Концептуально у вас есть:

(val1, val2, val3) IS NOT NULL

против

NOT (val1, val2, val3) IS NULL

Теперь, в первом случае, вы получите TRUE, если каждый из val1, val2 и val3 не равен NULL. Во втором случае вы получите TRUE, если какой-либо из val1, val2, val3 не является NULL. Таким образом, существуют ситуации, когда две операции не идентичны.

Однако, как я уже говорил, для обычного случая простого столбца или выражения нет разницы между ними.