使用Oracle 11g中的+符号左外连接

时间:2011-07-02 19:50:08

标签: sql oracle11g

任何人都可以告诉我下面的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

6 个答案:

答案 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 vs LEFT

我看到了一些关于在隐式连接语法中确定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 。它们是写作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

请注意,这与上面发布的内容相反。我想这本书有可能有勘误表,但是我比本书中的内容更信任这本书。这是一个大声呼喊的考试指南......