在 Oracle 11g 中使用 + 符号实现左外联接

谁能告诉我下面两个查询是左外联接还是右外联接的例子?

Table Part:
Name         Null?       Type
PART_ID      NOT NULL    VARCHAR2(4)
SUPPLIER_ID              VARCHAR2(4)


PART_ID SUPPLIER_ID
P1      S1
P2      S2
P3
P4


Table Supplier:
Name            Null?     Type
SUPPLIER_ID NOT NULL      VARCHAR2(4)
SUPPLIER_NAME   NOT NULL  VARCHAR2(20)


SUPPLIER_ID  SUPPLIER_NAME
S1           Supplier#1
S2           Supplier#2
S3           Supplier#3

显示所有零件,无论是否有供应商提供:

SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE P.Supplier_Id = S.Supplier_Id (+)


SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE S.Supplier_Id (+) = P.Supplier_Id
580628 次浏览

这两个查询正在执行 OUTER JOIN

Oracle 建议使用 FROM 子句 OUTERJOIN 语法 外部连接查询使用 Oracle 连接操作符(+)遵守以下规则 限制,这些限制不适用于 FROM 子句 OUTERJOIN 句法:

  • 不能在查询块中指定(+)运算符 包含 FROM 子句连接语法。

  • (+)运算符只能出现在 WHERE 子句中,或者出现在 左相关的上下文(在指定 TABLE 子句时) FROM 子句,并且只能应用于表或视图的列。

  • 如果 A 和 B 由多个连接条件连接,则必须使用 (+)操作符。如果没有,则 Oracle 数据库将只返回由简单 加入,但没有一个警告或错误,告诉你,你不 获得外部连接的结果

  • 如果指定了外部联接,(+)运算符不会产生外部联接 外部查询中的表和内部查询中的另一个表。

  • 不能使用(+)运算符将表与其自身进行外部连接, 尽管自连接是有效的 无效:

    -- The following statement is not valid:
    SELECT employee_id, manager_id
    FROM employees
    WHERE employees.manager_id(+) = employees.employee_id;
    

    但是,以下自联接是有效的:

    SELECT e1.employee_id, e1.manager_id, e2.employee_id
    FROM employees e1, employees e2
    WHERE e1.manager_id(+) = e2.employee_id
    ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
    
  • The (+) operator can be applied only to a column, not to an arbitrary expression. However, an arbitrary expression can contain one or more columns marked with the (+) operator.

  • A WHERE condition containing the (+) operator cannot be combined with another condition using the OR logical operator.

  • A WHERE condition cannot use the IN comparison condition to compare a column marked with the (+) operator with an expression.

If the WHERE clause contains a condition that compares a column from table B with a constant, then the (+) operator must be applied to the column so that Oracle returns the rows from table A for which it has generated nulls for this column. Otherwise Oracle returns only the results of a simple join.

In a query that performs outer joins of more than two pairs of tables, a single table can be the null-generated table for only one other table. For this reason, you cannot apply the (+) operator to columns of B in the join condition for A and B and the join condition for B and C. Refer to SELECT for the syntax for an outer join.

Taken from http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm

TableA LEFT OUTER JOIN TableB等于 TableB RIGHT OUTER JOIN Table A

在 Oracle 中,(+)表示 JOIN 中的“可选”表。所以在第一个查询中,它是 P LEFT OUTER JOIN S。在第二个查询中,它是 S RIGHT OUTER JOIN P它们在功能上是等价的。

在术语中,RIGHT 或 LEFT 指定联接的哪一边始终有一条记录,而另一边可能为 null。所以在 P LEFT OUTER JOIN S中,P总是有一条记录,因为它在 LEFT上,但是 S可能为空。

有关更多说明,请参见 这个例子来自 java2s.com


为了澄清,我想我是说术语并不重要,因为它只是用来帮助形象化的。重要的是你了解它是如何工作的。


右对左

在隐式连接语法中,我已经看到了一些关于确定右与左的重要性的混淆。

左外连接

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外连接

SELECT *
FROM A, B
WHERE B.column(+) = A.column

我所做的只是在 WHERE 子句中交换术语的两侧,但它们在功能上仍然是等价的。(更多信息请参见我的回答。)(+)的位置决定向右还是向左。(具体来说,如果 (+)在右边,那么它是一个左连接。如果 (+)在左边,则为右连接。)


连接的类型

两种风格的连接是 隐式连接显式连接。它们是编写 JOIN 的不同风格,但是它们在功能上是等价的。

参见 这个所以问题

隐式 JOIN 简单地将所有表列在一起。

隐式加入

SELECT *
FROM A, B
WHERE A.column = B.column(+)

显式 JOIN 将连接条件与特定表的包含相关联,而不是在 WHERE 子句中。

明确加入

SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column

这些 隐式 JOIN 可能更难以阅读和理解,而且它们还有一些限制,因为连接条件与其他 WHERE 条件混合在一起。因此,通常建议反对使用隐式 JOIN,以支持显式语法。

这个帖子里有一些不正确的信息,我复制粘贴了这些不正确的信息:

左外连接

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外连接

SELECT *
FROM A, B
WHERE B.column(+) = A.column

上面的内容是错误的! ! ! ! ! ! 它是反过来的。我是从下面这本书中判断它是错误的:

Oracle OCP Oracle 9i 简介: SQL 考试指南 。表3-1对此有一个很好的总结。我不知道为什么我转换的 SQL 不能正常工作,直到我去老学校,并在一本印刷书看!

以下是这本书的摘要,逐行复制:

Oracle 外部联接语法:

from tab_a a, tab_b b,
where a.col_1 + = b.col_1

ANSI/ISO 等效标准:

from tab_a a left outer join
tab_b b on a.col_1 = b.col_1

注意这里是上面贴出的内容的反面。我认为这本书有可能有错误,但是我更相信这本书,而不是这个线索中的内容。这是考试指南。

我在上面的答案中看到了一些矛盾之处,我只是在 Oracle 12c 上尝试了下面的方法,下面的方法是正确的:

左外连接

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外连接

SELECT *
FROM A, B
WHERE B.column(+) = A.column

左外连接

选择 * 从 A,B WHERE A.column = B.column (+)

右外连接

选择 * 从 A,B WHERE A.column (+) = B.column

You can see answers from previous posts
However I added little more information
create table r2020 (id int, name varchar2(50),rank number);
insert into r2020 values (101,'Rob Rama',1);
insert into r2020 values (102,'Ken Krishna',3);
insert into r2020 values (108,'Ray Rama',2);
insert into r2020 values (109,'Kat Krishna',4);
    

create table r2021 (id int, name varchar2(50),rank number);
insert into r2021 values (102,'Ken Krishna',1);
insert into r2021 values (103,'Tom Talla',2);
insert into r2021 values (108,'Ray Rama',2);
    

--LEFT OUTER JOIN
--oracle notation
select * from r2020 r1, r2021 r2
where  r1.id  = r2.id (+)
order by r1.id;
        

--ANSI notation
select * from r2020 r1
left outer join r2021 r2 on  r1.id = r2.id
order by r1.id;
--OUT PUT
NAME        ID RANK  NAME_1     ID_1    RANK_1
----        -- ---- ----        ----   ------
Rob Rama    101 1   (null)      (null)  (null)
Ken Krishna 102 3   Ken Krishna 102     1
Ray Rama    108 2   Ray Rama    108     2
Kat Krishna 109 4   (null)      (null)  (null)
    

--RIGHT OUTER JOIN
--oracle notation
select * from r2020 r1, r2021 r2
where  r1.id (+)  = r2.id
order by r1.id;
        

--ANSI notation
select * from r2020 r1
right outer join r2021 r2 on  r1.id = r2.id
order by r1.id;
--OUT PUT
NAME        ID    RANK    NAME_1      ID_1    RANK_1
----        --    ----    ----        ----   ------
Ken Krishna 102     3     Ken Krishna 102    1
Ray Rama    108     2     Ray Rama    108    2
(null)      (null) (null) Tom Talla   103    2
        

        

--<b>MULTIPLE COLUMNS IN JOIN CONDITION</b>
--LEFT OUTER JOIN
--oracle notation
select * from r2020 r1, r2021 r2
where  r1.id  = r2.id (+) and
r1.rank  = r2.rank (+)
order by r1.id;
        

--ANSI notation
select * from r2020 r1
left outer join r2021 r2 on  r1.id = r2.id and
r1.rank  = r2.rank
order by r1.id;
--OUT PUT
NAME        ID RANK  NAME_1     ID_1    RANK_1
----        -- ---- ----        ----   ------
Rob Rama    101 1   (null)      (null)  (null)
Ken Krishna 102 3   (null)      (null)  (null)
Ray Rama    108 2   Ray Rama    108     2
Kat Krishna 109 4   (null)      (null)  (null)
    

--RIGHT OUTER JOIN
--oracle notation
select * from r2020 r1, r2021 r2
where  r1.id (+)  = r2.id and
r1.rank(+)  = r2.rank
order by r1.id;
        

--ANSI notation
select * from r2020 r1
right outer join r2021 r2 on  r1.id = r2.id and
r1.rank  = r2.rank
order by r1.id;
--OUT PUT
NAME      ID     RANK   NAME_1       ID_1  RANK_1
----      --     ----   ----         ----  ------
(null)    (null) (null) Ken Krishna  102   1
Ray Rama  108     2     Ray Rama     108   2
(null)    (null) (null) Tom Talla    103   2

要编写一个查询,执行表 A 和 B 的外部连接并返回来自 A 的所有行(左外部连接) ,可以在 FROM 子句中使用 LEFT [ OUTER ] JOIN 语法,或者在 WHERE 子句的连接条件中对 B 的所有列应用外部连接操作符(+)