web-dev-qa-db-ja.com

OracleUSING句のベストプラクティス

免責事項:私は開発者であり、DBAではありません。

私はOracleのUSING句を偶然見つけて、それ以来、ファクトテーブルとディメンションテーブルを結合するために昔ながらのON句の代わりにそれを使用して以来、大ファンでした。私にとっては、はるかに簡潔なSQLを作成し、不要な重複列のない、より簡潔な結果セットを生成します。

しかし、昨日、同僚からすべてのUSING句をONに変換するように依頼されました。私は彼に確認し、彼の理由を尋ねます。彼は私よりもデータベースと緊密に連携しているので、彼にはいくつかの正当な理由があると思います。

彼からの返信はありませんが(さまざまなタイムゾーンで作業しています)、「using」句の使用に関するガイドラインやベストプラクティスはありますか?私はかなりググったが、決定的なものに出くわしたことはない。実際、私はどこでも良い議論すらしていません。

誰かがこれに光を当てることができますか?または、トピックに関する適切なディスカッションへのリンクを提供しますか?

ありがとうございました!

10
RAY

あなたはおそらくすでにその違いを知っていますが、 ドキュメント から:

ONconditionON句を使用して、結合条件を指定します。そうすることで、WHERE句の検索条件またはフィルター条件とは別に結合条件を指定できます。

USING(column両方のテーブルで同じ名前の列の等結合を指定する場合、USING column句は、使用する列を示します。この句は、両方のテーブルの結合列の名前が同じである場合にのみ使用できます。この句内では、列名をテーブル名またはテーブルエイリアスで修飾しないでください。

したがって、これらは同等になります。

select e.ename, d.dname
from emp e join dept d using (deptno);

select e.ename, d.dname
from emp e join dept d on d.deptno = e.deptno;

使用する大部分はスタイルの問題ですが、(少なくとも)usingを使用できない状況が2つあります。(a)2つのテーブルで列名が同じでない場合、および(b)結合列を使用する場合:

select e.ename, d.dname, d.deptno
from emp e join dept d using(deptno);

select e.ename, d.dname, d.deptno
                         *
ERROR at line 1:
ORA-25154: column part of USING clause cannot have qualifier

もちろん、それを使用して結合されていない同じ列を持つ別のテーブルがない限り、修飾子とselect ..., deptnoを省略できます。

select e.ename, d.dname, deptno
from emp e join dept d using (deptno) join mytab m using (empno);

select e.ename, d.dname, deptno
                         *
ERROR at line 1:
ORA-00918: column ambiguously defined

その場合、修飾されたm.deptnoのみ選択できます。 (OK、これはかなり不自然です...)。

usingを回避するために私が見ることができる主な理由は、一貫性だけです。使用できない場合もあるため、そのような状況でonに切り替えると少し不快になる場合があります。しかし、繰り返しになりますが、それは技術的な理由よりもスタイルに関するものです。

おそらくあなたの同僚は単にコーディング標準を課している(または提案している)のですが、それを知っているのは彼らだけです。また、レビュー中の、作成した新しいコードを変更するように求められているのか、古いコードを変更するように求められているのかも、はっきりしていません。後者の場合、onを好む理由に関係なく、変更されたコードが再テストされても新しい問題が発生するリスクがあるため、証明されたコードを変更するための個別の正当化を取得する必要があると思います-やり直しと再テストに伴うコスト/労力は別として。

しかし、あなたの質問についていくつかのことが私を襲います。最初に、on構文を「昔ながらの」と説明しますが、それは公平ではないと思います。どちらも有効で最新のものです(SQL:2011の時点では、引用が必要です!)。この:

不要な重複列のない、より簡潔な結果セットを生成します。

...これはselect *を使用していることを示唆していると思います。そうでない場合は、修飾子にいくつかの余分な文字がありますが、値の1つを選択するだけです。 select *の使用は、アドホッククエリと一部のサブクエリ以外の場合は一般的に悪い習慣と見なされます(たとえば、 ここ )。

25
Alex Poole

関連する質問

主な違いは構文にあるようです。列はUSING結合でマージされます。

すべての場合において、これは、特定のテーブルから結合された列の値にアクセスできないことを意味します。実際には、一部のSQLはコンパイルされません。次に例を示します。

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT 1 a, 2 b, 3 c FROM dual)
  3  SELECT t.* FROM t JOIN v USING (a);

SELECT t.* FROM t JOIN v USING (a)
         ^    
ORA-25154: column part of USING clause cannot have qualifier

外部結合では、これは外部テーブルの値にアクセスできないことを意味します。

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT NULL a, 2 b, 3 c FROM dual)
  3  SELECT * FROM t LEFT JOIN v USING (a)
  4   WHERE v.a IS NULL;

 WHERE v.a IS NULL
         ^
ORA-25154: column part of USING clause cannot have qualifier

これは、USING句を使用したこの反結合構文に相当するものがないことを意味します。

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT NULL a, 2 b, 3 c FROM dual)
  3  SELECT * FROM t LEFT JOIN v ON v.a = t.a
  4   WHERE v.a IS NULL;

         A          B          C A          B          C
---------- ---------- ---------- - ---------- ----------
         1          2          3  

これとは別に、私は違いを認識していませんSQLが有効になったら

ただし、この構文はあまり一般的に使用されていないように思われるため、特にANSI SQLが導入された初期のバージョンでは、USING句のみに影響する特定のバグがあったとしても驚かないでしょう。 MOSでこれを確認できるものは何も見つかりませんでした。これは、[〜#〜] using [〜#〜]Wordがバグの説明に遍在しています。

この機能を使用しない理由がバグによるものである場合、立証責任は同僚にあるように思われます。バグにパッチを適用すると、最終的に禁止を解除できるように、バグを参照/文書化する必要があります(データベースアップグレード...)。

理由が表面的なものまたはコーディング規約の一部である場合は、それも文書化する必要があります。

2
Vincent Malgrat

USINGを使用すると、次のような結合も実行できません。selecta.id、aval、bval、cval from a.id = b.id left join c on c.id = b.id;

つまり、Cの列は、Bテーブルの行と一致する場合にのみ指定します。

0
Jon Waterhouse