最初の理論:Null(SQL)
上記のリンクからの私たちにとって最も重要な部分:
NULLおよび3値論理(3VL)との比較
Nullはどのデータドメインのメンバーでもないため、「値」とは見なされず、値がないことを示すマーカー(またはプレースホルダー)と見なされます。このため、Nullとの比較では、TrueまたはFalseになることはありませんが、常に3番目の論理結果であるUnknownになります。[8]値10をNullと比較する以下の式の論理結果は不明です:
SELECT 10 = NULL -- Results in Unknown
両方の比較:x = NULL
およびx <> NULL
NULL(不明)と評価されます。
SQLは3つの論理結果を実装するため、SQL実装は特殊な3値論理(3VL)を提供する必要があります。 SQLの3値論理を管理するルールを以下の表に示します(pとqは論理状態を表します)。含意の定義が異なりますが、SQLではそのような操作は定義されていません。
+---------+-------------+-------------+-------------+-----------+--------+ | p | q | p OR q | p AND q | p = q |p != q | +---------+-------------+-------------+-------------+-----------+--------+ | True | True | True | True | True | False | | True | False | True | False | False | True | | True | Unknown | True | Unknown | Unknown | Unknown| | False | True | True | False | False | True | | False | False | False | False | True | False | | False | Unknown | Unknown | False | Unknown | Unknown| | Unknown | True | True | Unknown | Unknown | Unknown| | Unknown | False | Unknown | False | Unknown | Unknown| | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown| +---------+-------------+-------------+-------------+-----------+--------+
WHERE句での不明の影響
SQL 3値論理は、DMLステートメントとクエリの比較述語のデータ操作言語(DML)で検出されます。 WHERE句を使用すると、DMLステートメントは、述語がTrueと評価された行にのみ作用します。
つまり、WHERE句はNULLをFALSEとして扱います
ここで、より単純なケースを考えてみてください:
SELECT * FROM T1;
| X |
|--------|
| 1 |
| (null) |
とクエリ:
SELECT * FROM t1 WHERE x IN (1, NULL);
上記のクエリは、このクエリの短縮形です:
SELECT * FROM t1
WHERE x = 1
OR x = NULL
テーブルt
の2行目 (x =NULL)この条件は次のようになります:
WHERE NULL = 1
OR NULL = NULL
したがって、行x=NULL
のこの条件 NULL=1
であるため、NULLと評価されます NULL、NULL=NULL
はNULLであり、NULL OR NULL
もNULLです(上記の表3VLを参照してください)。
次に、もっと奇妙なケースを考えてみましょう:
SELECT * FROM t1 WHERE x NOT IN (1, NULL);
この句x NOT IN (1, NULL)
NOT ( x IN (1, NULL) )
と同等です
したがって、次と同等です:
NOT (
x = 1
OR
x = NULL
)
ド・モルガンの法則によれば、次のようになります。
NOT ( x = 1 ) AND NOT ( x = NULL )
および(NOT x = y
を置き換える場合 x <> y
を使用 )これは次と同等でもあります:
x <> 1 AND x <> NULL
最後の状態をよく見てください:
WHERE
x <> 1 AND x <> NULL
x <> NULL
よりもわかっています 常にNULLと評価されます。上記の3VLテーブルから、true AND NULL
の両方であることがわかります。 NULLでfalse AND NULL
FALSEと評価されるため、条件全体は常にFALSEまたはNULLと評価されますが、TRUEと評価されることはありません。
したがって、この条件のクエリ:
SELECT .....
WHERE x NOT IN ( NULL, whatever)
常に空の結果セットを返します
そして今、あなたのクエリも興味深いです:
SELECT * FROM t1
WHERE (id, val) NOT IN (select id, val from data2);
これは(定数値を使用して)次のように書き換えることができます:
SELECT * FROM t1
WHERE (id, val) NOT IN (
(1, null),
(2, 2 )
)
このクエリは、いわゆる行値式を使用しています
基本的に、このような行値式を使用する条件
(a, b) = (x, y)
これと同等です:
a = x AND b = y
したがって、上記のクエリは次のクエリに書き換えることができます:
SELECT * FROM t1
WHERE NOT (
id = 1 AND val = NULL
OR
id = 2 AND val = 2
)
ドモルガンの法則によれば、これは次のようになります。
SELECT * FROM t1
WHERE
NOT ( id = 1 AND val = NULL )
AND
NOT ( id = 2 AND val = 2 )
さらに:
SELECT * FROM t1
WHERE
( id <> 1 OR val <> NULL )
AND
( id <> 2 OR val <> 2 )
最初の部分から( id <> 1 OR val <> NULL )
id <> 1
の場合にのみ、条件のがtrueと評価されます。 (上記の3VL表を参照してください)、この条件は次のように簡略化できます:
SELECT * FROM t1
WHERE
( id <> 1 )
AND
( id <> 2 OR val <> 2 )
さらに(ド・モルガンの法則に従って)次のようになります:
SELECT * FROM t1
WHERE
id <> 1 AND id <> 2
OR
id <> 1 AND val <> 2
したがって、どちらも(1,1)
(2,2)
でもありません ソースからdata1
これらの条件を遵守してください。