Вы должны различать две ситуации: вы сравниваете одну СТОЛБЦУ с NULL или сравниваете всю строку (RECORD) с NULL.
Рассмотрим следующий запрос:
SELECT
id,
txt,
txt IS NULL AS txt_is_null,
NOT txt IS NULL AS not_txt_is_null,
txt IS NOT NULL AS txt_is_not_null
FROM
(VALUES
(1::integer, NULL::text)
)
AS x(id, txt) ;
Вы получаете это:
+----+-----+-------------+-----------------+-----------------+
| id | txt | txt_is_null | not_txt_is_null | txt_is_not_null |
+----+-----+-------------+-----------------+-----------------+
| 1 | | t | f | f |
+----+-----+-------------+-----------------+-----------------+
Это, я думаю, то, что вы и я ожидали бы. Вы проверяете одну КОЛОННУ против NULL и получаете «txt IS NOT NULL» и «NOT txt IS NULL» эквивалентны.
Однако, если вы делаете другую проверку:
SELECT
id,
txt,
x IS NULL AS x_is_null,
NOT x IS NULL AS not_x_is_null,
x IS NOT NULL AS x_is_not_null
FROM
(VALUES
(1, NULL)
)
AS x(id, txt) ;
Тогда вы получите
+----+-----+-----------+---------------+---------------+
| id | txt | x_is_null | not_x_is_null | x_is_not_null |
+----+-----+-----------+---------------+---------------+
| 1 | | f | t | f |
+----+-----+-----------+---------------+---------------+
Это может быть удивительно. Одна вещь выглядит разумной (x IS NULL) и (NOT x IS NULL) противоположны друг другу. Другое дело (тот факт, что ни «x IS NULL», ни «x IS NOT NULL» не верны), выглядит странно.
Тем не менее, это то, что что должно произойти документации PostgreSQL :
Если выражение имеет строковое значение, то IS NULL имеет значение true, если само выражение строки равно нулю или когда все поля строки имеют значение null, тогда как IS NOT NULL равно true, если само выражение строки не равно нулю и все поля строки имеют значение ненулевой. Из-за этого поведения IS NULL и IS NOT NULL не всегда возвращают обратные результаты для выражений со значениями строк; в частности, строковое выражение, содержащее как нулевые, так и ненулевые поля, вернет false для обоих тестов. В некоторых случаях может быть предпочтительнее записать строку IS DISTINCT FROM NULL или строку NOT DISTINCT FROM NULL, которая просто проверит, является ли значение строки в целом нулевым, без каких-либо дополнительных тестов для полей строки.
Должен признаться, я не думаю, что когда-либо использовал строковое сравнение с нулем, но я предполагаю, что, если такая возможность есть, может быть какой-то вариант ее использования. Во всяком случае, я не думаю, что это обычное дело.