在我们正在迁移的一个基于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子句中使用?我从来没有见过这样的用法。
根据"(+) "在"="的哪一边,它表示左外连接或右外连接(在本例中,它是左外连接)。 这是老式的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
的列在查询结果中。这是一种非ANSI的左外连接符号,从Oracle9i开始,使用'(+)'符号的混乱的外连接语法已经被ISO 99外连接语法所取代。从Oracle9i开始,使用'(+)'符号的混乱的外连接语法已经被ISO 99外连接语法所取代。
值得注意的是,经典的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方法不会有新手程序员把(+)放错位置的风险。