Oracle的加号(+)表示法和ansi JOIN表示法之间的区别?

使用oracle的加号(+)加上ANSI标准join符号的区别是什么?

性能有差别吗?

加号表示是否被弃用?

AFAIK, (+)符号仅用于向后兼容性,因为Oracle在joinANSI标准之前已经推出了它。 这是Oracle特有的,如果存在等效的符合标准的版本,则应避免在新代码中使用它。

编辑: 似乎有两者之间的差异, (+)符号具有ANSI连接语法不具有的限制。 Oracle自己build议您不要使用(+)符号。 Oracle®数据库SQL语言参考11g第1版(11.1)中的完整描述:

Oraclebuild议您使用FROM子句OUTER JOIN语法而不是Oracle连接运算符。 使用Oracle连接运算符(+)外部连接查询受以下规则和限制的限制,这些规则和限制不适用于FROM子句OUTER JOIN语法:

  • 您不能在也包含FROM子句连接语法的查询块中指定(+)运算符。
  • (+)运算符只能出现在WHERE子句中,或者在FROM子句中的左相关(在指定TABLE子句时)中出现,并且只能应用于表或视图的列。
  • 如果A和B由多个连接条件连接,则必须在所有这些条件中使用(+)运算符。 如果不这样做,那么Oracle数据库将只返回由简单连接产生的行,但是没有警告或错误,通知您没有外连接的结果。

  • 如果在外部查询中指定了一个表,并且在内部查询中指定了另一个表,则(+)运算符不会生成外部联接。

  • 您不能使用(+)运算符将表外连接到自身,尽pipe自连接是有效的。

例如,以下语句无效:

 SELECT employee_id, manager_id FROM employees WHERE employees.manager_id(+) = employees.employee_id; 

但是,下面的自join是有效的:

 SELECT e1.employee_id, e1.manager_id, e2.employee_id FROM employees e1, employees e2 WHERE e1.manager_id(+) = e2.employee_id; 
  • (+)运算符只能应用于列,而不能应用于任意expression式。 但是,任意expression式可以包含一个或多个用(+)运算符标记的列。

  • 包含(+)运算符的WHERE条件不能与使用OR逻辑运算符的其他条件组合。

  • WHERE条件不能使用IN比较条件将(+)运算符标记的列与expression式进行比较。

如果WHERE子句包含将表B中的列与常量进行比较的条件,则必须将(+)运算符应用于该列,以便Oracle返回表A中已为其生成空值的行。 否则,Oracle只返回简单连接的结果。

在执行超过两对表的外部联接的查询中,一个表可以是只有一个其他表的空生成表。 因此,在A和B的连接条件以及B和C的连接条件中,不能将(+)运算符应用于B的列。有关外部连接的语法,请参阅SELECT

从Oracle 10开始,我们仍然支持该标记(我相信11)。 它的使用被认为是“老式的”,也不像ANSI JOIN语法那样可移植。 它也被认为是不太可读的,虽然如果你来自习惯于ANSI JOIN的+背景,可能需要一点时间。 在向Oracle投掷砖块之前,要知道的重要一点是在ANSI委员会完成连接的定义之前,他们开发了它们的+语法。

没有性能差异; 他们正在expression同样的事情。

编辑:“不如便携”我应该说“只有在Oracle SQL支持”

我同意托尼·米勒(Tony Miller)的回答,并且想补充一点,你也不能用(+)合成器做一些事情:

  • 您不能完全外联合两个表,你必须手动做一个联合所有的两个联接,
  • 你不能OUTER JOIN一个表到两个或更多的表,你必须手动创build一个子查询(即: b.id = a.id (+) AND c.id = a.id (+)不是一个可接受的条款)

最为全面的答案显然就是nagul 。

对于那些正在寻找快速翻译/映射到ANSI语法的人来说:

 -- -- INNER JOIN -- SELECT * FROM EMP e INNER JOIN DEPT d ON d.DEPTNO = e.DEPTNO; -- Synonym in deprecated oracle (+) syntax SELECT * FROM EMP e, DEPT d WHERE d.DEPTNO = e.DEPTNO; -- -- LEFT OUTER JOIN -- SELECT * FROM EMP e LEFT JOIN DEPT d ON d.DEPTNO = e.DEPTNO; -- Synonym in deprecated oracle (+) syntax SELECT * FROM EMP e, DEPT d WHERE d.DEPTNO (+) = e.DEPTNO; -- -- RIGHT OUTER JOIN -- SELECT * FROM EMP e RIGHT JOIN DEPT d ON d.DEPTNO = e.DEPTNO; -- Synonym in deprecated oracle (+) syntax SELECT * FROM EMP e, DEPT d WHERE d.DEPTNO = e.DEPTNO(+); -- -- CROSS JOIN -- SELECT * FROM EMP e CROSS JOIN DEPT d; -- Synonym in deprecated oracle (+) syntax SELECT * FROM EMP e, DEPT d; -- -- FULL JOIN -- SELECT * FROM EMP e FULL JOIN DEPT d ON d.DEPTNO = e.DEPTNO; -- Synonym in deprecated oracle (+) syntax !NOT WORKING! SELECT * FROM EMP e, DEPT d WHERE d.DEPTNO (+) = e.DEPTNO(+); 

Oracle(+)符号仅在Oracle中使用,这是特定供应商的 。 而且, ANSI标准join符号用于任何RDBMS(如Sql Server,MySql等) 。 否则,Oracle(+)符号和ANSI standared Join符号之间没有区别。

如果您在Sql查询中使用ANSI标准join符号,则可以在任何RDBMS中使用相同的查询。 而且,如果在这种情况下数据库从Oracle 移植 到任何其他RDBMS ,则必须使用ANSI语法

在旧的Oracle连接语法上使用ANSI语法的一个很好的理由是,没有意外创build笛卡尔产品的机会是零。 有了更多的表格,就有可能错过使用较旧的Oracle连接语法的隐式连接,但是,使用ANSI语法,您不能错过任何连接,因为您必须明确地提及它们。

Oracle外部连接语法ANSI / ISO语法之间的区别。

左外连接 –

 SELECT e.last_name, d.department_name FROM employees e, departments d WHERE e.department_id = d.department_id(+); SELECT e.last_name, d.department_name FROM employees e LEFT OUTER JOIN departments d ON (e.department_id = d.department_id); 

RIGHT OUTER JOIN –

 SELECT e.last_name, d.department_name FROM employees e, departments d WHERE e.department_id(+) = d.department_id; SELECT e.last_name, d.department_name FROM employees e RIGHT OUTER JOIN departments d ON (e.department_id = d.department_id); 

全外联接 –

在11gR1的散列完全外连接的本地支持之前,Oracle会按照以下方式在内部转换全外连接:

 SELECT e.last_name, d.department_name FROM employees e, departments d WHERE e.department_id = d.department_id(+) UNION ALL SELECT NULL, d.department_name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.department_id ); SELECT e.last_name, d.department_name FROM employees e FULL OUTER JOIN departments d ON (e.department_id = d.department_id); 

看看这个 。

  1. 使用显式JOIN而不是隐式(不pipe是否是外连接)是因为使用隐式连接意外创build笛卡尔积更容易。 有了明确的JOIN,你不能“无意”地创build一个JOIN。 涉及的表越多,风险就越高,因此错过了一个连接条件。
  2. 与ANSIjoin相比,基本上(+)是严格限制的。 此外,它仅在Oracle中可用,而ANSI连接语法由所有主要DBMS支持
  3. 在迁移到ANSI语法之后,SQL将无法更好地执行 – 这只是不同的语法。
  4. Oracle强烈build议您使用前例中显示的更灵活的FROM子句连接语法。 过去有一些ANSI语法的错误,但是如果你使用最新的11.2或12.1版本,应该已经修复了。
  5. 使用JOIN运算符可确保您的SQL代码符合ANSI标准,从而可以使前端应用程序更容易地移植到其他数据库平台。
  6. 连接条件在每个表上具有非常低的select性,并且在理论交叉乘积中对元组具有高select性。 where语句中的条件通常具有更高的select性。
  7. Oracle在内部将ANSI语法转换为(+)语法,您可以在执行计划的谓词信息部分看到这一点。

我使用(+)符号,因为几乎所有Oracle应用程序r12相关的查询都基于此。 我还没有看到在Oracle APPS查询中使用标准“连接”expression式的单个SQL查询(甚至是Oracle本身提供的查询)。 如果你不相信我,只需要谷歌任何与Oracle应用程序相关的信息。 例如: 固定资产相关查询