10

SQL 結合の NATURAL 短縮形について読んでいるのですが、いくつかのトラップがあります。

  • 同じ名前のすべての列ペアが自動的に取得されます (USING を使用して明示的な列リストを指定します)。
  • いくつかの新しい列が追加された場合、結合出力も「予期せず」変更される可能性があります。これは、複雑な構造では (NATURAL の仕組みを知っていても) それほど明白ではない場合があります。
4

6 に答える 6

20

NATURAL JOIN構文はアンチパターンです:

  • クエリの目的はそれほど明白ではありません。
    • アプリケーションで使用される列が明確ではありません
    • 使用される列は「予期せず」変更される可能性があります
  • 構文は、可能な限り厳密な型指定を使用することについて、モジュール性の規則に反します。Explicitは、ほぼ普遍的に優れています。

このため、どの環境でも構文をお勧めしません。
また、構文を混在させることはお勧めしません(つまりNATURAL JOIN、明示的なINNER / OUTER JOIN構文の両方を使用する)-一貫したコードベース形式を維持します。

于 2011-05-18T04:07:44.830 に答える
7

自然な結合に反対しているように見えるこれらの「トラップ」は、両方の道を切り開きます。テーブルAに新しい列を追加し、テーブルBとの結合に使用されることを完全に期待しているとします。AとBのすべての結合が自然結合であることがわかっている場合は、これで完了です。すべての結合が明示的にUSINGを使用している場合は、それらをすべて追跡して変更する必要があります。1つミスし、バグがあります。

テーブルのセマンティクスがこれが正しいことであると示唆している場合は、NATURAL結合を使用します。テーブル定義がどのように進化するかに関係なく、特定の方法で結合が行われるようにする場合は、明示的な結合基準を使用します。

于 2011-05-18T04:06:57.710 に答える
5

私にとって完全に破壊されることの1つNATURALは、ほとんどのテーブルにid列があり、それは明らかに意味的にすべて異なるということです。user_idを持っている方がより理にかなっていると主張することもできますが、そうすると、DRYの違反のidようなものを書くことになります。また、同じロジックで、、、 ...user.user_idのような列もあります(これは、たとえば、ホラーとは異なるという観点からも意味があります)。user_first_nameuser_last_nameuser_agesession_age

頑張りますJOIN ... ON ...、ありがとうございました。:)

于 2011-05-18T04:12:36.160 に答える
3

明確にするために明示的な結合を使用し、要件が変更された場合に「OUTER」結合への切り替えを簡単に許可する必要があるという他のポスターに同意します。

ただし、ほとんどの「トラップ」は結合とは関係ありませんが、「SELECT a.col1、a.col2、b.col1、b.col2」を必要とする列に明示的に名前を付ける代わりに「SELECT *」を使用することの悪さです。これらのトラップは、ワイルドカード列リストが使用されるたびに発生します。

于 2011-05-18T04:15:58.170 に答える
2

上記の回答のいずれにも記載されていない理由を追加します。postgres では (これが他のデータベースに当てはまるかどうかは不明です)、使用時に 2 つのテーブル間で共通の列名が見つからない場合NATURAL JOIN、aCROSS JOINが実行されます。これは、既存のクエリがあり、その後テーブル内の列名の 1 つを変更した場合でも、エラーではなくクエリから一連の行が返されることを意味します。代わりにJOIN ... USING(...)構文を使用すると、結合する列がなくなった場合にエラーが発生します。

postgresのドキュメントには、この趣旨のメモがあります。

注: USING は、リストされた列のみが結合されるため、結合されたリレーションの列の変更に対してかなり安全です。NATURAL は、いずれかのリレーションにスキーマを変更すると、一致する新しい列名が存在するようになると、結合によってその新しい列も結合されるため、かなりリスクが高くなります。

于 2016-10-27T17:21:20.817 に答える
-2

次のような構文を意味しますか?

SELECT * 
  FROM t1, t2, t3 ON t1.id = t2.id 
                 AND t2.id = t3.id

これに対して:

         SELECT *  
           FROM t1 
LEFT OUTER JOIN t2 ON t1.id = t2.id 
                  AND t2.id = t3.id

私は2番目の構文を好み、フォーマットも異なります。

         SELECT *
           FROM T1
LEFT OUTER JOIN T2 ON T2.id = T1.id
LEFT OUTER JOIN T3 ON T3.id = T2.id

この場合、結合しているテーブルと、それらを結合するために使用しているON句は非常に明確です。その最初の構文を使用することにより、適切なJOINを入れずに、膨大な結果セットを取得するのは簡単すぎます。私はタイプミスを起こしやすいのでこれを行います、そしてこれはそれに対する私の保険です。さらに、視覚的にデバッグが容易です。

于 2011-05-18T04:10:54.347 に答える