32

前文

最近、Oracle に関する質問に「(+) 演算子を使用しないでください。JOIN 構文を使用してください」とコメントしているオタクが多すぎるのを目にします。

質問

どちらもうまく機能していることがわかります。しかし、それらを使用することの本当の違いは何ですか? 経験からの回答を歓迎します。

  1. 使用中のアプリケーション、パフォーマンスなどの制限について何か関係はありますか?
  2. あなたは私に何を提案しますか?

Oracle のドキュメントを読んだことはありますが、包括的な情報を理解するには十分ではありません。

: (+) の代わりにキーワードを使用する必要がある場合は、200 以上のパッケージと手順を移行する予定です。

  1. また、書き換えを行うためのフリーウェア ツールはありますか?

掲載サンプル

┌───────────────────────────────────┬─────────────────────────────────────────────┐
│ INNER JOIN - CONVENTIONAL         │ INNER JOIN - ANSI SYNTAX                    │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │       ename,                                │
│ FROM                              │       dname,                                │
│      emp,                         │       emp.deptno,                           │
│      dept                         │       dept.deptno                           │
│ WHERE                             │ FROM                                        │
│      emp.deptno = dept.deptno;    │       scott.emp INNER JOIN scott.dept       │
│                                   │       ON emp.deptno = dept.deptno;          │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ LEFT OUTER JOIN - CONVENTIONAL    │ LEFT OUTER JOIN - ANSI SYNTAX               │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │      ename,                                 │
│ FROM                              │      dname,                                 │
│      emp,                         │      emp.deptno,                            │
│      dept                         │      dept.deptno                            │
│ WHERE                             │ FROM                                        │
│      emp.deptno = dept.deptno(+); │      scott.emp LEFT OUTER JOIN scott.dept   │
│                                   │      ON emp.deptno = dept.deptno;           │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ RIGHT OUTER JOIN - CONVENTIONAL   │ RIGHT OUTER JOIN - ANSI SYNTAX              │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │      ename,                                 │
│ FROM                              │      dname,                                 │
│      emp,                         │      emp.deptno,                            │
│      dept                         │      dept.deptno                            │
│ WHERE                             │ FROM                                        │
│      emp.deptno(+) = dept.deptno; │      scott.emp RIGHT OUTER JOIN scott.dept  │
│                                   │      ON emp.deptno = dept.deptno;           │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ FULL OUTER JOIN - CONVENTIONAL    │ FULL OUTER JOIN - ANSI SYNTAX               │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      *                            │      *                                      │
│ FROM                              │ FROM                                        │
│      emp,                         │      scott.emp FULL OUTER JOIN scott.dept   │
│      dept                         │      ON emp.deptno = dept.deptno;           │
│ WHERE                             │                                             │
│      emp.deptno = dept.deptno(+)  │                                             │
│ UNION ALL                         │                                             │
│ SELECT                            │                                             │
│      *                            │                                             │
│ FROM                              │                                             │
│      emp,                         │                                             │
│      dept                         │                                             │
│ WHERE                             │                                             │
│      emp.deptno(+) = dept.deptno  │                                             │
│      AND emp.deptno IS NULL;      │                                             │
└───────────────────────────────────┴─────────────────────────────────────────────┘

PS : グループ化されたすべての更新プログラムの回答の概要をお読みください。

4

11 に答える 11

25

200 以上のパッケージが「昔ながらの」構文で意図したとおりに機能する場合は、そのままにしておいてください。ANSI 構文に移行した後、SQL のパフォーマンスが向上するわけではありません。構文が異なるだけです。

そうは言っても、ANSI 構文はきれいです。複数列の外部結合で (+) を忘れると、通常の結合にはなりません。
過去に ANSI 構文にいくつかのバグがありましたが、最新の 11.2 または 12.1 を使用する場合は、既に修正されているはずです。
もちろん、自分の環境と優先順位をよく知っているでしょう - SchmitzIT が言ったように - ANSI 構文は SQL 標準の一部であり、他の RDBMS 製品を使用するときに役立ちます。

于 2013-09-22T13:52:28.810 に答える
14

11g では、ANSI 結合構文を使用する必要があります。より柔軟 (完全な外部結合と分割結合のサポート) であり、ドキュメントには次のように記載されています。

前の例に示した、より柔軟な FROM 句の結合構文を使用することを強くお勧めします。

それは十分な理由です。

于 2013-09-19T09:43:07.980 に答える
10

回答をグループ化する

  1. (外部結合であるかどうかに関係なく) 暗黙的ではなく明示的な JOIN を使用すると、暗黙的な結合を使用してデカルト積を誤って作成することがはるかに簡単になります。明示的な JOIN を使用すると、「偶然に」JOIN を作成することはできません。関係するテーブルが多いほど、1 つの結合条件を見逃すリスクが高くなります。
  2. 基本的に (+) は、ANSI 結合に比べて大幅に制限されています。さらに、ANSI 結合構文はすべての主要な DBMS でサポートされているのに対し、Oracle でのみ使用できます。
  3. ANSI 構文に移行した後、SQL のパフォーマンスが向上するわけではありません。構文が異なるだけです。
  4. 前の例に示した、より柔軟な FROM 句の結合構文を使用することを強くお勧めします。過去に ANSI 構文にいくつかのバグがありましたが、最新の 11.2 または 12.1 を使用する場合は、既に修正されているはずです。
  5. JOIN 演算子を使用すると、SQL コードが ANSI 準拠であることを確認できるため、フロントエンド アプリケーションを他のデータベース プラットフォームに簡単に移植できます。
  6. 結合条件では、各テーブルの選択性が非常に低く、理論上の外積のタプルの選択性が高くなります。where ステートメントの条件は、通常、はるかに高い選択性を持っています。
  7. Oracle は内部的に ANSI 構文を (+) 構文に変換します。これは、実行計画の述語情報セクションで確認できます。

12c エンジンで ANSI 構文を使用する際の落とし穴

12c の JOIN にバグの可能性が含まれています。こちらをご覧ください

ファローアップ:

Quest SQL optimizer toolSQL を ANSI 構文に書き直します。

于 2013-10-01T10:39:28.443 に答える
5

他の人が言及した理由とは別に、JOIN 演算子を使用すると、SQL コードが ANSI 準拠であることを確認できるため、フロントエンド アプリケーションを他のデータベース プラットフォームに簡単に移植できます。

于 2013-09-22T12:35:09.413 に答える
2

私はさまざまなプロジェクトで両方のアプローチを使用しましたが、JOIN構文を好みます。

  • ON句の結合条件と句のフィルタ条件は明確に分離されていWHEREます。
  • 多数の結合を使用した大規模なクエリの読み取りと維持が容易になります。
于 2013-09-24T16:45:20.683 に答える