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