Oracle:在WHERE子句中,`(+)`是什么意思?

72

我们正在迁移一个基于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子句中的作用是什么?我以前从来没有见过它被这样使用。


4
还有遗留的 TSQL (SQL Server) 中的 *==* 运算符,情况类似。 - user166390
2
相关:在Oracle 11g中使用+符号的左外连接 - Jonathan Lonowski
4个回答

107

根据“(+)”在“=”的哪一边,它表示LEFT OUTER或RIGHT OUTER连接(在这种情况下,它是左外部连接)。由于这是旧的Oracle语法,有些人会更喜欢使用它,因为它可以让他们的代码更短。

但为了可读性,请最好不要使用它。


2
很遗憾,Oracle 8 中不支持 ANSI 连接语法。因此,在这种情况下,您需要坚持使用 (+) 语法。 - Cheekysoft
2
遗憾的是,在 Oracle 11 中,使用 FAST REFRESH ON COMMIT 选项的 MATERIALIZED VIEW 不支持 ANSI JOINS。因此,在这种情况下,仍需要使用 (+) 语法。 - Sandre

26

正如其他人所述,(+)语法是已过时的专有语法,Oracle使用多年以实现与 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 中有匹配行的情况,将这些行也包括进来(如果在 Table2 中存在多个匹配行,则会重复 Table1 中的内容)。
  • 对于那些在 Table2 中没有匹配行的情况,在查询结果中使用 NULL 来代替 Table2 的所有列。

5

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


2
只是挑刺一下:标准的OUTER JOIN语法是在SQL-92中引入的。 - Bill Karwin

4

需要注意的是,经典的Oracle表示法并不直观,从代码清晰度和可维护性的角度来看,最好避免使用。

为了阐明这一点,我将举一个例子。

要在表A和表B之间实现LEFT OUTER JOIN,人们会期望左边的表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 方法不会有新手程序员错误地将 (+) 放在错误的位置的风险。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接