65

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

4 回答 4

97

根据“=”的哪一侧,“(+)”表示左外连接或右外连接(在这种情况下,它是左外连接)。这是旧的 Oracle 语法,有时会被那些首先学习它,因为他们喜欢它使他们的代码更短。

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

于 2009-01-10T00:46:45.453 回答
25

正如其他人所说,该(+)语法是过时的,Oracle 多年来使用的专有语法来实现与OUTER JOIN. 我假设他们在 SQL-92 决定标准语法之前采用了他们的专有语法。

使用标准 SQLOUTER 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重复内容)。Table1Table2
  • 如果 中没有匹配的行Table2,则NULL用于查询结果中的所有Table2列。
于 2009-01-10T00:52:50.853 回答
5

这是一种非 ANSI 左外连接表示法。从 Oracle9i 开始,使用 '(+)' 符号的令人困惑的外连接语法已被 ISO 99 外连接语法所取代。

于 2009-01-10T00:42:18.363 回答
3

一个值得注意的考虑是经典的 Oracle 表示法不直观,最好从代码清晰度和可维护性的角度避免。

为了说明这一点,我已经包含了这个例子。

为了实现LEFT outer join表之间的a 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 方法不会带来新手程序员错误地将 (+) 放在错误位置的风险。

于 2020-04-27T21:03:50.030 回答