任何人都可以告诉我下面的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
答案 0 :(得分:179)
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指定连接的哪一侧始终具有记录,而另一侧可能为空。因此,在P LEFT OUTER JOIN S
中,P
始终会有记录,因为它位于LEFT
上,但S
可能为空。
有关其他说明,请参阅this example from java2s.com。
澄清一下,我想我说这个术语并不重要,因为它只是帮助可视化。重要的是你了解它的工作原理。
我看到了一些关于在隐式连接语法中确定RIGHT与LEFT的重要性的混淆。
LEFT OUTER JOIN
SELECT *
FROM A, B
WHERE A.column = B.column(+)
RIGHT OUTER JOIN
SELECT *
FROM A, B
WHERE B.column(+) = A.column
我所做的就是交换WHERE子句中的术语,但它们在功能上仍然相同。 (有关详细信息,请参阅我的答案中的更高位置。)(+)
的展示位置确定为RIGHT或LEFT。 (具体来说,如果(+)
位于右侧,则为LEFT JOIN。如果(+)
位于左侧,则为正确加入。)
JOIN的两种样式是隐式JOIN 和显式JOIN 。它们是写作JOIN的不同风格,但它们在功能上是等价的。
请参阅this SO question。
隐式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
这些 隐式JOIN可能更难以阅读和理解,并且它们也有一些限制,因为连接条件在其他WHERE条件中混合。因此,通常建议使用隐式JOIN来支持显式语法。
答案 1 :(得分:8)
这两个查询正在执行OUTER JOIN
。见下文
Oracle建议您使用FROM子句OUTER JOIN语法 而不是Oracle join运算符。使用的外部联接查询 Oracle连接运算符(+)遵循以下规则和 限制,不适用于FROM子句OUTER JOIN 语法:
您也无法在查询块中指定(+)运算符 包含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;
(+)运算符只能应用于列,而不能应用于任意列 表达。但是,任意表达式可以包含一个或 更多列标有(+)运算符。
无法组合包含(+)运算符的WHERE条件 使用OR逻辑运算符的另一个条件。
WHERE条件不能使用IN比较条件来比较a 用(+)运算符标记的列。
如果WHERE子句包含比较列的条件 表B带有常量,那么(+)运算符必须应用于 列,以便Oracle返回表A中的行 为此列生成空值。否则Oracle只返回 简单连接的结果。
在执行两对以上表的外连接的查询中, 单个表可以是仅为另一个表生成的空表 表。因此,您不能将(+)运算符应用于列 B和A的连接条件中的B和B的连接条件 和C.有关外连接的语法,请参阅SELECT。
取自http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm
答案 2 :(得分:2)
我在上面的答案中看到了一些矛盾,我在Oracle 12c上尝试了以下内容,以下是正确的:
LEFT OUTER JOIN
SELECT *
FROM A, B
WHERE A.column = B.column(+)
RIGHT OUTER JOIN
SELECT *
FROM A, B
WHERE B.column(+) = A.column
答案 3 :(得分:0)
左外连接
选择* 从A,B A.column = B.column(+)
右外连接
选择* 从A,B A.列(+)= B.列
答案 4 :(得分:0)
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
答案 5 :(得分:-2)
此线程中有一些不正确的信息。我复制并粘贴了不正确的信息:
LEFT OUTER JOIN
SELECT * FROM A, B WHERE A.column = B.column(+)
RIGHT OUTER JOIN
SELECT * FROM A, B WHERE B.column(+) = A.column
以上是错误的!!!!!这是相反的。我如何确定它是不正确的是来自下面的书:
Oracle OCP Introduction to Oracle 9i: SQL Exam Guide。表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
请注意,这与上面发布的内容相反。我想这本书有可能有勘误表,但是我比本书中的内容更信任这本书。这是一个大声呼喊的考试指南......