Oracle:"(+) "在WHERE子句中的作用是什么?

问题描述 投票:58回答:4

在我们正在迁移的一个基于Oracle的应用程序中发现了以下内容。(一般化):

SELECT
    Table1.Category1,
    Table1.Category2,
    count(*) as Total,
    count(Tab2.Stat) AS Stat
FROM Table1, Table2
WHERE (Table1.PrimaryKey = Table2.ForeignKey(+))
GROUP BY Table1.Category1, Table1.Category2

什么是 (+) 在WHERE子句中使用?我从来没有见过这样的用法。

sql oracle operators
4个回答
91
投票

根据"(+) "在"="的哪一边,它表示左外连接或右外连接(在本例中,它是左外连接)。 这是老式的Oracle语法,有时会被先学过的人所喜欢,因为他们喜欢这样能让他们的代码更短。

不过为了可读性,最好不要用它。


24
投票

就像其他人所说的那样 (+) 语法是过时的,专有的语法,甲骨文多年来一直使用该语法来实现与一个 OUTER JOIN. 我想他们在SQL-92决定标准语法之前就采用了他们的专有语法。

相当于你所展示的查询,使用标准的 SQL OUTER JOIN 语法(现在所有主要的RDBMS实现都支持)如下。

SELECT
    Table1.Category1,
    Table1.Category2,
    COUNT(*) AS Total,
    COUNT(Table2.Stat) AS Stat
FROM Table1
  LEFT OUTER JOIN Table2 ON (Table1.PrimaryKey = Table2.ForeignKey)
GROUP BY Table1.Category1, Table1.Category2;

这意味着:

  • 所有来自 Table1 被包含在查询结果中。
  • 如果有匹配的记录在 Table2,包括这些行(重复内容从 Table1 如果有多条匹配的记录 Table2).
  • 如果在 Table2,使用 NULL 对于所有 Table2的列在查询结果中。

5
投票

这是一种非ANSI的左外连接符号,从Oracle9i开始,使用'(+)'符号的混乱的外连接语法已经被ISO 99外连接语法所取代。从Oracle9i开始,使用'(+)'符号的混乱的外连接语法已经被ISO 99外连接语法所取代。


0
投票

值得注意的是,经典的Oracle符号并不直观,从代码清晰度和可维护性的角度来看,最好避免使用这种符号。

为了说明这一点,我加入了这个例子。

为了实现 LEFT outer join 表间 AB 人们会认为左边的表,也就是A应该有(+)操作符在它旁边。这是有道理的,因为我们想表示我们将包括A表的所有记录,而不管连接标准是否成功,与B表的连接是否成功。

select b.age, a.name
from Employees a, EmployeeUNI b
where a.id = b.id(+)

我更喜欢ANSI SQL版本,它是显式的。

select b.age, a.name
From Employees a 
    LEFT outer join EmployeeUNI b
on a.id = b.id

两种方法的输出结果是一样的,但是ANSI方法不会有新手程序员把(+)放错位置的风险。

© www.soinside.com 2019 - 2024. All rights reserved.