Oracle:`(+)` 在 WHERE 子句中的作用是啥?

Posted

技术标签:

【中文标题】Oracle:`(+)` 在 WHERE 子句中的作用是啥?【英文标题】:Oracle: What does `(+)` do in a WHERE clause?Oracle:`(+)` 在 WHERE 子句中的作用是什么? 【发布时间】:2010-09-30 15:00:05 【问题描述】:

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

【问题讨论】:

还有旧版 TSQL (SQL Server) *==* 运算符。同一条船。 我在 Oracle 的 SQL 查询中寻找这些 (+) 的含义。并且无法使用 Google 搜索 (+)。我前往 Stack Overflow,Stack Overflow 的搜索引擎给了我 (+) 的零结果。这是错误的。 Stack Overflow 上至少有两个关于(+) 含义的问题。改正搜索引擎就好了。 相关:Difference between Oracle's plus (+) notation and ansi JOIN notation? 相关:Left Outer Join using + sign in Oracle 11g 【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

正如其他人所说,(+) 语法是过时的专有语法,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 中没有匹配的行,则对查询结果中Table2 的所有列使用NULL

【讨论】:

【参考方案3】:

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

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

【讨论】:

感谢您提供有关(+)= 之间方向的额外花絮。 - .5 表示更长的可读性。 a++ 比 a = a + 1 更难阅读。我认为如果您知道它的含义,它会容易得多。如果你不知道这意味着什么,请退出我的代码。 @Mark -- 在过去的 8 年里,我一直使用 Perl 作为我的母语进行编程。如果你还没有学会简短和晦涩的区别,请不要碰我的代码! 不幸的是,ANSI 连接语法在 Oracle 8 中不可用。所以在这种情况下您需要坚持使用 (+) 语法。 不幸的是,带有 FAST REFRESH ON COMMIT 选项的 MATERIALIZED VIEW 不支持 ANSI JOINS (Oracle 11)。所以在这种情况下你仍然需要 (+) 语法。【参考方案4】:

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

【讨论】:

只是吹毛求疵:标准的 OUTER JOIN 语法是在 SQL-92 中引入的。 对不起,您的答案是第一个......赞成。留下我的,因为它有额外的信息:左与右外。

以上是关于Oracle:`(+)` 在 WHERE 子句中的作用是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle - where 子句中的案例

在 where 子句中的 Oracle 集合

where 子句 oracle 中的 case 语句

在 where 子句问题中的 Oracle 日期比较

oracle中where子句和having子句中的区别

oracle中where 子句和having子句中的区别