使用oracle加上符号(+)
而不是ansi标准join
表示法有什么区别?
性能有差异吗?
加号表示法是否已弃用?
答案 0 :(得分:96)
AFAIK,(+)
表示法仅用于向后兼容,因为Oracle在加入ANSI标准之前就推出了它。它是特定于Oracle的,当有相同的符合标准的版本时,你应该避免在新代码中使用它。
编辑: 两者之间似乎存在差异,(+)
符号具有ANSI连接语法所没有的限制。 Oracle自己建议您不要使用(+)
表示法。
Oracle® Database SQL Language Reference
11g Release 1 (11.1)中的完整说明:
Oracle建议您使用FROM
子句OUTER JOIN
语法而不是Oracle join运算符。使用Oracle连接运算符(+)
的外连接查询受以下规则和限制的约束,这些规则和限制不适用于FROM
子句OUTER JOIN
语法:
(+)
子句连接语法的查询块中指定FROM
运算符。(+)
运算符只能出现在WHERE
子句中,或者在TABLE
子句中左对齐(指定FROM
子句时)的上下文中出现,并且只能应用于表格或视图的列。如果A和B通过多个连接条件连接,则必须在所有这些条件下使用(+)
运算符。如果不这样做,那么Oracle数据库将仅返回由简单连接产生的行,但没有警告或错误,建议您没有外连接的结果。
如果在外部查询中指定一个表而在内部查询中指定另一个表,则(+)
运算符不会生成外部联接。
虽然自联接有效,但您无法使用(+)
运算符将表外连接到自身。
例如,以下语句无效:
SELECT employee_id, manager_id
FROM employees
WHERE employees.manager_id(+) = employees.employee_id;
但是,以下自加入有效:
SELECT e1.employee_id, e1.manager_id, e2.employee_id
FROM employees e1, employees e2
WHERE e1.manager_id(+) = e2.employee_id;
(+)
运算符只能应用于列,而不能应用于任意表达式。但是,任意表达式可以包含一个或多个标有(+)
运算符的列。
包含WHERE
运算符的(+)
条件无法与使用OR
逻辑运算符的其他条件合并。
WHERE
条件无法使用IN
比较条件将标有(+)
运算符的列与表达式进行比较。
如果WHERE
子句包含将表B中的列与常量进行比较的条件,则必须将(+)
运算符应用于该列,以便Oracle返回表A中的行,它为此列生成了空值。否则,Oracle仅返回简单连接的结果。
在执行两个以上表对的外连接的查询中,单个表可以是仅为一个其他表的空生成表。因此,您不能将(+)
运算符应用于A和B的连接条件中的B列以及B和C的连接条件。有关外连接的语法,请参阅SELECT
。
答案 1 :(得分:12)
从Oracle 10开始仍然支持该表示法(我相信11)。它的使用被认为是“老式的”,并且不像ANSI JOIN语法那样是数据库可移植的。它也被认为更不易读,虽然如果你来自+背景习惯ANSI JOIN可能需要一点时间。在向Oracle投掷砖块之前要知道的重要事项是,在ANSI委员会完成连接定义之前,他们开发了+语法。
没有性能差异;他们表达同样的事情。
编辑:通过“不那么便携”我应该说“只在Oracle SQL中支持”
答案 2 :(得分:12)
我同意Tony Miller的回答,并想补充一点,你可以用(+)synthax做一些事情:
b.id = a.id (+) AND c.id = a.id (+)
不是可接受的子句)答案 3 :(得分:9)
最全面的答案显然是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(+);
答案 4 :(得分:2)
使用 ANSI 语法优于旧的 Oracle加入语法的一个很好的理由是,没有机会意外创建笛卡儿产品。有了更多的表,有可能错过使用旧的Oracle连接语法的隐式连接,但是,使用ANSI语法,您不能错过任何连接,因为您必须明确提及它们。
Oracle外连接语法与 ANSI / ISO语法之间的区别。
LEFT 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
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);
FULL OUTER JOIN -
在11gR1中对hash full outerjoin进行原生支持之前,Oracle会在内部以下列方式转换FULL OUTER JOIN -
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);
查看this。
答案 5 :(得分:1)
Oracle(+)表示法仅用于Oracle,特定于供应商。并且, ANSI标准加入符号可以用于任何RDBMS(如Sql Server,MySql等)。否则,Oracle(+)表示法和ANSI标准加入表示法之间没有区别。
如果您在Sql Query中使用ANSI标准连接表示法,则可以在任何RDBMS中使用相同的查询。并且,如果您移植您的数据库<强>从Oracle到任何其他RDBMS 在这种情况下你必须使用ANSI语法。
答案 6 :(得分:1)
我使用(+)表示法,因为几乎所有与Oracle Apps r12相关的查询都基于此。我没有在Oracle APPS查询中看到一个带有标准“join”表达式的SQL查询(甚至是Oracle本身提供的那些)。如果您不相信我,只需谷歌任何Oracle应用相关信息。例如:Fixed assets related queries
答案 7 :(得分:1)