Oracle:WHERE子句中`(+)`做什么?

时间:2009-01-10 00:41:31

标签: sql oracle operators

在我们正在迁移(通用)的基于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 个答案:

答案 0 :(得分:88)

根据“=”的哪一侧“(+)打开,它表示LEFT OUTER或RIGHT OUTER join(在这种情况下,它是左外连接)。它是旧的Oracle语法,有时是首选由首先学习它的人,因为他们喜欢它,使他们的代码更短。

为了便于阅读,最好不要使用它。

答案 1 :(得分:23)

正如其他人所说,(+)语法是过时的专有语法,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中有匹配的行,请包含这些行(如果Table1中有多个匹配的行,则重复Table2的内容)。
  • 如果Table2中没有匹配的行,请对查询结果中的所有NULL列使用Table2

答案 2 :(得分:5)

它是非ANSI左外连接表示法。从Oracle9i开始,使用'(+)'表示法的混淆外连接语法已被ISO 99外连接语法取代。

答案 3 :(得分:0)

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

为说明这一点,我提供了此示例。

要在表LEFT outer joinA之间实现B,可以期望左边的表A旁边应该有(+)运算符。正如我们要表示的那样,这将是有道理的,无论与B的连接条件是否成功,我们都将包括A的所有行。但是,事实并非如此,并且可以按以下方式实现连接

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方法不会带来新手程序员错误地将(+)放在错误位置的风险。