Oracle联接 - 传统语法VS ANSI语法之间的比较

Sri*_*niV 29 sql oracle oracle10g oracle11g oracle12c

前言

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

我确实看到两者都运作良好.但是使用它们之间的真正区别是什么让你觉得使用它们?我希望得到答案,更多来自经验.

 1. Is there anything to do with limitations in application, performance, 
    etc. while using them?

 2. What would you suggest for me?
Run Code Online (Sandbox Code Playgroud)

我确实阅读了有关Oracle文档的内容,但还不足以让我理解或对综合信息感到满意.

注意:如果要使用关键字而不是(+),我打算迁移200多个包和程序

  3. Also is there any freeware tools to do the rewrite?
Run Code Online (Sandbox Code Playgroud)

发布样本

???????????????????????????????????????????????????????????????????????????????????
? 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;      ?                                             ?
???????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

PS:阅读所有分组更新的答案摘要.

igr*_*igr 24

如果您的200多个软件包使用"老式"语法按预期工作,那就试试吧.迁移到ANSI语法后,SQL不会开始表现更好 - 它只是不同的语法.

总而言之,ANSI语法更清晰 - 如果在某些多列外连接中忘记(+),则不会进行正常连接.
在过去,有一些ANSI语法的错误,但如果你使用最新的11.2或12.1应该已经修复.
当然,您更了解您的环境和优先级 - 正如SchmitzIT所说 - ANSI语法是SQL标准的一部分,它将有助于使用其他一些RDBMS产品.


Dav*_*dge 14

在11g中,您应该使用ANSI连接语法.它更灵活(支持完全外连接和分区连接),并且文档说明:

Oracle强烈建议您使用前一个示例中显示的更灵活的FROM子句连接语法.

这就足够了.

  • @itmitică更准确地说,您可以使用组合的左右连接结果集构建外部联接结果,但是您也可以通过UNIONing内部联接和两个查询来构造相同的内部联接而不需要任何外部联接存在相关子查询.所以我认为我的发言是有效的. (2认同)

Sri*_*niV 10

将答案分组在一起

  1. 使用显式JOIN而不是隐式(无论它们是否为外连接)是因为使用隐式连接意外创建笛卡尔积更容易.使用显式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的可能性.看到这里

跟进:

Quest SQL optimizer tool 将SQL重写为ANSI语法.


Sch*_*zIT 5

除了其他人提到的原因之外,使用JOIN运算符可确保您的SQL代码符合ANSI标准,从而可以更轻松地将前端应用程序移植到其他数据库平台.


小智 5

作为实践,您应该始终使用 ANSI 语法。最好不要对包和程序进行返工。相反,当您单独对这些脚本进行任何维护时,您可以修复问题。由于语法的原因,计划不会有任何差异。

Quest SQL 优化器使用所有可能的组合进行重写,以找到更好的计划。所以你仍然需要从 100 多个结果中搜索一条 SQL。