Oracle 联接 - 常规语法与 ANSI 语法的比较

2021-12-05 00:00:00 sql oracle11g oracle12c oracle oracle10g

序言

最近,我看到太多极客在评论 Oracle 问题时说不要使用 (+) 运算符,而是使用 JOIN 语法".

As of late, I see too many geeks commenting on Oracle questions saying "Do not use (+) operator, rather use JOIN syntax".

问题

我确实看到两者都运行良好.但是使用它们之间的真正区别是什么?我欢迎从经验中获得更多答案.

I do see that both work well. But what is the real difference between using them? I would welcome answers more from experience.

  1. 使用它们时是否与应用程序、性能等方面的限制有关?
  2. 你有什么建议给我?

我确实在 Oracle 文档a> 但不足以让我理解或对全面的信息感到满意.

I did read something on Oracle documentation but it’s not good enough to make me understand or feel comfortable with the comprehensive information.

注意:我计划迁移 200 多个包和程序,如果应该使用关键字而不是 (+)

Note: I am planning to migrate 200+ packages and procedures, if the Keyword should be used instead of (+)

  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:阅读分组的所有更新的答案摘要.

PS: Read the summary of answers for all updates grouped.

推荐答案

将答案分组

  1. 使用显式联接而不是隐式联接(无论它们是否是外联接),因为使用隐式联接意外创建笛卡尔积要容易得多.使用显式 JOIN,您不能意外"创建一个.涉及的表越多,您错过一个连接条件的风险就越高.
  2. 与 ANSI 连接相比,基本上 (+) 受到严重限制.此外,它仅在 Oracle 中可用,而所有主要 DBMS 都支持 ANSI 连接语法
  3. 在迁移到 ANSI 语法后,SQL 不会开始表现得更好——它只是不同的语法.
  4. Oracle 强烈建议您使用前一个示例中显示的更灵活的 FROM 子句连接语法.过去,ANSI 语法存在一些错误,但如果您使用最新的 11.2 或 12.1,应该已经修复了.
  5. 使用 JOIN 运算符可确保您的 SQL 代码符合 ANSI,从而使前端应用程序可以更轻松地移植到其他数据库平台.
  6. 连接条件对每个表的选择性非常低,而对理论叉积中的元组具有很高的选择性.where 语句中的条件通常具有更高的选择性.
  7. Oracle 在内部将 ANSI 语法转换为 (+) 语法,您可以在执行计划的谓词信息部分看到这种情况.

在 12c 引擎上使用 ANSI 语法的可能陷阱

包括 12c 中 JOIN 中可能存在的错误.请参阅此处

Including a possibility of bug in JOIN in 12c. See here

跟进:

Quest SQL 优化器工具 将 SQL 重写为 ANSI 语法.

Quest SQL optimizer tool rewrites the SQL to ANSI syntax.

相关文章