![](/img/trans.png)
[英]How to using Left Outer Join or Right Outer Join in Oracle 11g
[英]Left Outer Join using + sign in Oracle 11g
谁能告诉我以下 2 个查询是左外连接还是右外连接的示例?
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
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
可能是 null。
有关其他说明,请参阅java2s.com 中的此示例。
为了澄清,我想我是说术语并不重要,因为它只是为了帮助形象化。 重要的是您了解它如何工作的概念。
对于在隐式连接语法中确定 RIGHT 与 LEFT 的重要性,我已经看到了一些混淆。
左外连接
SELECT *
FROM A, B
WHERE A.column = B.column(+)
右外连接
SELECT *
FROM A, B
WHERE B.column(+) = A.column
我所做的只是交换 WHERE 子句中术语的两边,但它们在功能上仍然是等效的。 (有关更多信息,请参阅我的答案中的上层。) (+)
的位置决定了 RIGHT 或 LEFT。 (具体来说,如果(+)
在右侧,则为 LEFT JOIN。如果(+)
在左侧,则为 RIGHT JOIN。)
JOIN 的两个 styles 是隐式 JOIN和显式 JOIN 。 它们是写JOIN的不同styles,但功能上是等价的。
请参阅这个 SO 问题。
隐式 JOIN只是将所有表一起列出。 连接条件在 WHERE 子句中指定。
隐式连接
SELECT *
FROM A, B
WHERE A.column = B.column(+)
显式 JOIN将连接条件与特定表的包含相关联,而不是在 WHERE 子句中。
显式连接
SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column
这些隐式连接可能更难以阅读和理解,并且它们也有一些限制,因为连接条件混合在其他 WHERE 条件中。 因此,通常不建议使用隐式 JOIN,以支持显式语法。
这两个查询正在执行OUTER JOIN
。 见下文
Oracle 建议您使用 FROM 子句 OUTER JOIN 语法,而不是 Oracle 连接运算符。 使用 Oracle 连接运算符 (+) 的外部连接查询受以下规则和限制的约束,这些规则和限制不适用于 FROM 子句 OUTER JOIN 语法:
您不能在还包含 FROM 子句连接语法的查询块中指定 (+) 运算符。
(+) 运算符只能出现在 WHERE 子句中,或者在 FROM 子句中的左相关上下文中(当指定 TABLE 子句时),并且只能应用于表或视图的列。
如果 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;
(+) 运算符只能应用于列,不能应用于任意表达式。 但是,任意表达式可以包含一个或多个标有 (+) 运算符的列。
包含 (+) 运算符的 WHERE 条件不能与使用 OR 逻辑运算符的另一个条件组合。
WHERE 条件不能使用 IN 比较条件将标有 (+) 运算符的列与表达式进行比较。
如果 WHERE 子句包含将表 B 中的列与常量进行比较的条件,则必须将 (+) 运算符应用于该列,以便 Oracle 返回表 A 中已为此列生成空值的行。 否则 Oracle 仅返回简单连接的结果。
在执行多于两对表的外连接的查询中,单个表可以是仅为一个其他表生成的空表。 因此,不能将 (+) 运算符应用于 A 和 B 的连接条件以及 B 和 C 的连接条件中的 B 列。 有关外连接的语法,请参阅 SELECT。
取自http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm
我在上面的答案中看到了一些矛盾,我只是在 Oracle 12c 上尝试了以下内容,以下是正确的:
左外连接
SELECT *
FROM A, B
WHERE A.column = B.column(+)
右外连接
SELECT *
FROM A, B
WHERE B.column(+) = A.column
左外连接
SELECT * FROM A, B WHERE A.column = B.column(+)
右外连接
SELECT * FROM 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
此线程中有一些不正确的信息。 我复制并粘贴了错误的信息:
左外连接
SELECT * FROM A, B WHERE A.column = B.column(+)
右外连接
SELECT * FROM A, B WHERE B.column(+) = A.column
以上是错误的。:!!! 这是相反的。 我如何确定它不正确来自以下书籍:
Oracle OCP Oracle 9i 简介:SQL 考试指南。 第 115 页 表 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
请注意,这与上面发布的内容相反。 我想这本书可能有勘误表,但是我更相信这本书而不是这个线程中的内容。 这是大声哭泣的考试指南...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.