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

问题描述 投票:0回答: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个回答
105
投票

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

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


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
    中有匹配行的地方,包括那些行(如果
    Table1
    中有多个匹配行,则重复
    Table2
    中的内容)。
  • 如果
    Table2
    中没有匹配的行,则对查询结果中所有
    NULL
    的列使用
    Table2

5
投票

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


4
投票

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

为了说明这一点,我提供了这个例子。

为了在表

LEFT outer join
A
之间实现
B
,人们会期望左边的表 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.