回答:
結合のためにnullをnullと等しくできないのはなぜですか?
Oracleにそれを行うように指示するだけです。
select *
from one t1
join two t2 on coalesce(t1.id, -1) = coalesce(t2.id, -1);
(標準SQLではt1.id is not distinct from t2.id
、null-safeの等価演算子を取得するために使用できますが、Oracleはそれをサポートしていません)
ただし、これは、置換値(上記の例では-1)が実際にテーブルに表示されない場合にのみ機能します。そのような数値の「マジック」値を見つけることは可能かもしれませんが、文字値にとっては非常に困難です(特にOracleは空の文字列も処理するためnull
)
さらに、id
列のインデックスは使用されません(ただし、式で関数ベースのインデックスを定義できますcoalesce()
)。
マジック値なしで、すべてのタイプで機能する別のオプション:
on t1.id = t2.id or (t1.id is null and t2.id is null)
しかし、本当の質問は次のとおりです。これは理にかなっていますか?
次のサンプルデータを検討してください。
表1
id
----
1
2
(null)
(null)
表2
id
----
1
2
(null)
(null)
(null)
ヌル値の組み合わせのどれを結合で選択する必要がありますか?上記の例では、すべてのnull値のクロスジョインのような結果になります。
T1_ID | T2_ID
-------+-------
1 | 1
2 | 2
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
またはINTERSECT
、等値演算子として2つのnullを互いに一致させることができます。
SELECT
*
FROM
t1
INNER JOIN t2
ON EXISTS (SELECT t1.ID FROM DUAL INTERSECT SELECT t2.ID FROM DUAL)
;
図については、このDBFiddleデモを参照してください。
もちろん、これはかなり口に見えますが、実際にはBriteSpongeの提案よりもそれほど長くはありません。しかし、もしあなたがしゃれを許せば、コメントの標準的な方法で前述した簡潔さ、つまりIS NOT DISTINCT FROM
Oracleでまだサポートされていない演算子とは一致しません。
完全を期すためSYS_OP_MAP_NONNULL
に、12cのドキュメントに記載されているように、nullの値を比較するために関数を安全に使用できることに言及します。これは、Oracleが単にランダムにそれを削除してコードを壊さないことを意味します。
SELECT *
FROM one t1
JOIN two t2
ON SYS_OP_MAP_NONNULL(t1.id) = SYS_OP_MAP_NONNULL(t2.id)
利点は、「マジック」番号の問題に出くわさないことです。
Oracleドキュメントのリファレンスは、「基本マテリアライズドビュー-マテリアライズドビューのインデックスの選択」にあります。
結合でnull値を使用できないのはなぜですか?Oracleでは、次の両方がtrueと評価されません。
NULL = NULL
NULL <> NULL
これが、null値をチェックするIS NULL
/ を持っている理由IS NOT NULL
です。
これをテストするには、次のようにします。
SELECT * FROM table_name WHERE NULL = NULL
結合はブール条件を評価しており、異なる動作をするようにプログラムしていません。結合条件に大なり記号を入れて、他の条件を追加できます。ブール式として評価するだけです。
一貫性を保つために、結合でnullをnullと等しくすることはできません。比較演算子の通常の動作を無視します。
NULL = anything
NULL
SQL標準がそう言うので、結果。行が結合条件を満たしているのは、式が真の場合のみです。
ほとんどのリレーショナルデータベースのNULL値は、不明と見なされます。すべてのHEXゼロと混同しないでください。何かにnull(不明)が含まれている場合は、比較できません。
Unknown = Known False
Unknown = Unknown False
Unknown >= Known False
Known >= Unknown False
つまり、ブール式のオペランドとしてnullがある場合、else部分は常にtrueになります。
開発者によるnullに対する一般的な嫌悪とは反対に、nullには代わりがあります。不明な場合は、nullを使用します。
UNKNOWN
ではなくFALSE
;)
where (a = b or (a is null and b is null))
です。期間。それが私の考えです。私は使用を検討しませんsys_op_map_nonnull
、カーテンの後ろのその男を無視します。」