Oracle的plus()表示法和ansi JOIN表示法之间的区别?

's the difference between using oracle' s加上符号 (+) 超过ansi标准 join 符号?

性能有差异吗?

加号表示法是否已弃用?

回答(8)

2 years ago

AFAIK, (+) 符号仅用于向后兼容,因为Oracle在ANSI标准加入之前就推出了它 . 它's specific to Oracle and you should avoid using it in new code when there'是一个等效的符合标准的版本 .

Edit: It seems there are differences between the two, and the (+) notation has restrictions that the ANSI join syntax does not have. Oracle themselves recommend that you not use the (+) notation. Full description here in the Oracle® Database SQL Language Reference 11g Release 1 (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的连接条件 . 有关外连接的语法,请参阅 SELECT .

2 years ago

从Oracle 10开始仍然支持该表示法(我相信11) . 它的使用被认为是“老式的”,并且不像ANSI JOIN语法那样可以移植数据库 . 它也被认为更不易读,尽管如果你来自后台习惯ANSI JOIN可能需要一点时间 . 在向Oracle投掷砖块之前要知道的重要事项是,他们在ANSI委员会完成连接定义之前就开发了它们的语法 .

没有性能差异;他们表达了同样的话 .

编辑:通过“不可移植”我应该说“只在Oracle SQL中支持”

2 years ago

我同意Tony Miller的回答,并想补充说,还有一些你不能用()synthax做的事情:

  • 你不能FULL OUTER JOIN两个表,你必须手动使用UNION ALL两个连接,

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

2 years ago

最全面的答案显然是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(+);

2 years ago

使用 ANSI 语法而不是旧 Oracle join syntax 的一个很好的理由是,没有机会偶然创建一个 cartesian product . 有了更多的表,有可能错过使用旧的Oracle连接语法的 implicit 连接,但是,使用ANSI语法,您不能错过任何连接,因为您必须提及它们 .

Oracle outer join syntaxANSI/ISO Syntax 之间的区别 .

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 .

2 years ago

Oracle (+) notation 仅用于Oracle,即 vendor specific . 并且, ANSI standared Join notation 可以是 used in any RDBMS (like Sql Server,MySql etc.) . 否则,Oracle()表示法和ANSI标准加入之间没有区别符号 .

If you are using the ANSI standared Join notation in your Sql Query, you can use the same query in any RDBMS. 并且,如果你是 porting 你的数据库 from Oracle to any Other RDBMS 在这种情况下你必须 use ANSI Syntax .

2 years ago

我使用()表示法,因为几乎所有与Oracle Apps r12相关的查询都基于此 . 我've not seen a single SQL query with a standard 762383 expression in Oracle APPS queries(even the ones provided by Oracle itself). If you don' t相信我,只需谷歌任何Oracle应用程序相关信息 . 例如:Fixed assets related queries

2 years ago

  • 使用显式JOIN而不是隐式(无论它们是否是外连接)是因为使用隐式连接意外创建笛卡尔积更容易 . 使用显式JOIN,您不能"by accident"创建一个 . 涉及的表越多,您错过一个连接条件的风险就越高 .

  • 与ANSI连接相比,基本上()受到严重限制 . 此外,它仅在Oracle中可用,而所有主要DBMS都支持ANSI连接语法

  • 迁移到ANSI语法后SQL不会开始表现更好 - 它只是不同的语法 .

  • Oracle强烈建议您使用前一个示例中显示的更灵活的FROM子句连接语法 . 在过去,有一些ANSI语法的错误,但如果你使用最新的11.2或12.1应该已经修复 .

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

  • 连接条件对每个表具有非常低的选择性,并且对理论叉积中的元组具有高选择性 . where语句中的条件通常具有更高的选择性 .

  • Oracle在内部将ANSI语法转换为()语法,您可以在执行计划的谓词信息部分中看到这种情况 .