なぜx IS NOT NULL
と等しくないNOT x IS NULL
?
このコード:
CREATE TABLE bug_test (
id int,
name text
);
INSERT INTO bug_test
VALUES (1, NULL);
DO $$
DECLARE
v_bug_test bug_test;
BEGIN
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);
SELECT *
INTO v_bug_test
FROM bug_test
WHERE id = 1;
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);
END
$$;
DROP TABLE bug_test;
次の出力が得られます。
(,): t
(,): f
(,): f
(1,): f
(1,): f ???
(1,): t
私はこの出力を期待していますが:
(,): t
(,): f
(,): f
(1,): f
(1,): t <<<
(1,): t
2つの状況を区別する必要があります。1つのCOLUMNをNULLと比較するか、ROW(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に対して1つの列をチェックすると、 "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 |
+----+-----+-----------+---------------+---------------+
これは意外かもしれません。 1つは妥当に見えます(x IS NULL)と(NOT x IS NULL)は互いに逆です。他のこと(どちらも " x IS NULL "も" x IS NOT NULL "もtrue)で、奇妙に見えます。
しかし、これは PostgreSQLのドキュメント が言うべきことです:
式が行値の場合、IS NULLは、行式自体がnullである場合、または行のすべてのフィールドがnullである場合にtrueですが、IS NOT行式自体がnullでなく、すべての行のフィールドがnullでない場合、NULLはtrueです。この動作のため、IS NULLおよびIS NOT NULLは常に行値式の逆の結果を返すとは限りません。特に、nullフィールドと非nullフィールドの両方を含む行値式は、両方のテストでfalseを返します。場合によっては、行IS DISTINCT FROM NULLまたは行IS NOT DISTINCT FROM NULLと書くと、行全体の値がnullであるかどうかを確認せず、行フィールドに対する追加のテスト。
私はこれまでにnullに対する行値比較を使用したことはないと思いますが、可能性がある場合は、いくつかのユースケースがあると思います。とにかく、一般的ではないと思います。