Этот запрос дает ожидаемый результат:
SELECT *
FROM (SELECT 1 UNION ALL SELECT 2) AS tbl(col)
WHERE col IN (NULL, 1)
-- returns first row
Но добавление NOT
не инвертирует результаты:
SELECT *
FROM (SELECT 1 UNION ALL SELECT 2) AS tbl(col)
WHERE NOT col IN (NULL, 1)
-- returns zero rows
Это потому, что приведенный выше запрос примерно эквивалентен следующему:
SELECT *
FROM (SELECT 1 UNION ALL SELECT 2) AS tbl(col)
WHERE NOT (col = NULL OR col = 1)
А вот как вычисляется предложение where:
| col | col = NULL (1) | col = 1 | col = NULL OR col = 1 | NOT (col = NULL OR col = 1) |
|-----|----------------|---------|-----------------------|-----------------------------|
| 1 | UNKNOWN | TRUE | TRUE | FALSE |
| 2 | UNKNOWN | FALSE | UNKNOWN (2) | UNKNOWN (3) |
Обратите внимание, что:
- Сравнение с
NULL
выходами UNKNOWN
- Выражение
OR
, где ни один из операндов не равен TRUE
, а по крайней мере один операнд равен UNKNOWN
, дает UNKNOWN
( ref )
-
NOT
из UNKNOWN
дает UNKNOWN
( ref )
Вы можете расширить приведенный выше пример более чем на два значения (например, NULL, 1 и 2), но результат будет таким же: если одно из значений равно NULL
, то ни одна строка не будет соответствовать.
TLDR: все сводится к трехзначной логике, используемой в SQL. Чтобы победить SQL, вам нужно освоить его. Если вы не можете, просто следуйте совету , используйте NOT EXISTS
.