Oracle 的 plus (+)符号和 ansi JOIN 符号之间的区别?

使用 Oracle 的 + 符号 (+)和使用 ansi 标准的 join符号有什么区别?

在性能上有区别吗?

是否不推荐使用加号?

101676 次浏览

在 Oracle 10(我相信是11)中仍然支持这种表示法。它的使用被认为是“老式的”,而且也不像 ANSI JOIN 语法那样具有数据库可移植性。它也被认为是不太可读的,虽然如果你来自 + 背景习惯 ANSI JOIN 可能需要一点时间。在抨击 Oracle 之前,需要知道的重要一点是,在 ANSI 委员会完成连接的定义之前,Oracle 就已经开发出了 + 语法。

没有性能差异; 它们表达的是同一件事情。

编辑: 关于“不具有可移植性”,我应该说“只支持 Oracle SQL”

AFAIK,(+)表示法只是为了向后兼容而存在,因为 Oracle 是在 ANSI 连接标准到位之前首次使用它的。它是特定于 Oracle 的,当有一个等价的标准兼容版本可用时,应该避免在新代码中使用它。

似乎两者之间存在差异,而且 (+)符号有 ANSI 连接语法所没有的限制。Oracle 本身建议您不要使用 (+)表示法。 这里的完整描述见 http://download.Oracle.com/docs/cd/B28359 _ 01/server.111/b28286/queries006.htm rel = “ nofollow norefrer”> Oracle 数据库 SQL 语言参考 11g 第一版(11.1) :

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

  • 不能在也包含 FROM子句连接语法的查询块中指定 (+)运算符。
  • (+)运算符只能出现在 WHERE子句中,或者出现在 FROM子句的左相关上下文中(当指定 TABLE子句时) ,并且只能应用于表或视图的列。
  • 如果 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 的连接条件中的 B 列。有关外部连接的语法,请参阅 SELECT

我同意托尼 · 米勒的回答,并且想要补充的是,还有一些事情你不能用(+)语法来做:

  • 不能使用 FULL OUTER JOIN 两个表,必须手动使用 UNION ALL 两个连接,
  • 不能将表 OUTER JOIN 到两个或多个表,必须手动创建子查询(即: b.id = a.id (+) AND c.id = a.id (+)不是可接受的子句)

Oracle (+)符号 仅用于 Oracle,即 特定供应商ANSI 标准连接符号可以是 用于任何关系数据库管理系统(如 Sql 服务器、 MySql 等)。否则,Oracle (+)表示法和 ANSI 标准连接表示法之间没有区别。

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

我使用(+)表示法,因为几乎所有与 Oracle Apps r12相关的查询都是基于(+)表示法的。在 Oracle APPS 查询(甚至是 Oracle 自己提供的查询)中,我还没有看到一个带有标准“ join”表达式的 SQL 查询。如果你不相信我,只要谷歌任何甲骨文应用程序相关的信息。例如: 固定资产相关查询

最全面的答案显然是 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 连接语法上使用 ANSI语法的一个好的理由是,意外创建 笛卡儿积的可能性为零。对于更多的表,使用旧的 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);

右外连接

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,您不能“偶然”创建一个 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 语法转换为(+)语法,您可以在执行计划的谓词信息部分中看到这种情况。