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 表示法不直观,最好从代码清晰度和可维护性的角度避免使用。
为了说明这一点,我已经包含了这个例子。
要在表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 方法不会带来新手程序员错误地将 (+) 放在错误位置的风险。
【讨论】:
【参考方案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 子句中的作用是啥?的主要内容,如果未能解决你的问题,请参考以下文章