Left Outer Tham gia bằng + đăng nhập Oracle 11g


80

Có ai có thể cho tôi biết 2 truy vấn dưới đây là ví dụ của Left Outer Join hay Right Outer Join không ??

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

Hiển thị tất cả các bộ phận không phân biệt nhà cung cấp có cung cấp chúng hay không:

CHỌN P.Part_Id, S.Supplier_Name
TỪ Phần P, Nhà cung cấp S
WHERE P.Supplier_Id = S.Supplier_Id (+)

CHỌN P.Part_Id, S.Supplier_Name
TỪ Phần P, Nhà cung cấp S
WHERE S.Supplier_Id (+) = P.Supplier_Id

26
Bạn nên tránh sử dụng ký hiệu '(+)' và nâng cấp các truy vấn để sử dụng các phép nối rõ ràng.
Jonathan Leffler

1
@JonathanLeffler 100% đồng ý. Vấn đề là tôi làm việc với những người không muốn sử dụng ký hiệu tiêu chuẩn. Tôi viết truy vấn mới với ký hiệu tiêu chuẩn nhưng tôi sẽ xử lý sau một phút nếu truy vấn cũ được sửa đổi.
Luc M

3
@JonathanLeffler Tôi sẽ đồng ý, trừ khi bạn đang sử dụng Oracle. Oracle hiện tại không xử lý cú pháp ansi cũng như toán tử (+) bên trong. Mặc dù họ khuyên bạn nên sử dụng cú pháp ansi :) docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
Một câu chuyện thần thoại vào

7
@Amyth Xin lỗi vì cách này nhận xét đã lỗi thời, nhưng tôi đến với câu hỏi này từ một cuộc tìm kiếm. Đối với bản thân tôi, tôi hiểu các khuyến nghị của Oracle theo cách hoàn toàn ngược lại. Từ liên kết của bạn: " Oracle khuyến nghị bạn sử dụng cú pháp mệnh đề FROM OUTER JOIN chứ không phải toán tử tham gia Oracle. Các truy vấn kết hợp bên ngoài sử dụng toán tử tham gia Oracle (+) phải tuân theo các quy tắc và hạn chế sau, không áp dụng cho mệnh đề FROM OUTER JOIN ..."
Sylvain Leroux

Xin lỗi vì phản hồi đã lỗi thời :), nhưng những gì Oracle nói và cách thống kê của nó hoạt động để tối ưu hóa các truy vấn là hai điều khác nhau và có thể Oracle đã thay đổi lập trường của mình cũng như với những tiến bộ đối với các trình tối ưu hóa nội bộ của mình
Một huyền thoại

Câu trả lời:


186

TableA LEFT OUTER JOIN TableBtương đương với TableB RIGHT OUTER JOIN Table A.

Trong Oracle, (+)biểu thị bảng "tùy chọn" trong JOIN. Vì vậy, trong truy vấn đầu tiên của bạn, đó là một P LEFT OUTER JOIN S. Trong truy vấn thứ hai của bạn, đó là S RIGHT OUTER JOIN P. Chúng tương đương về mặt chức năng.

Trong thuật ngữ, RIGHT hoặc LEFT chỉ định phía nào của phép nối luôn có bản ghi và phía bên kia có thể là rỗng. Vì vậy, trong a P LEFT OUTER JOIN S, Psẽ luôn có một bản ghi vì nó ở trên LEFT, nhưng Scó thể là null.

Xem ví dụ này từ java2s.com để biết thêm giải thích.


Để làm rõ, tôi đoán tôi đang nói rằng thuật ngữ không quan trọng, vì nó chỉ ở đó để giúp hình dung. Điều quan trọng là bạn hiểu khái niệm về cách nó hoạt động.


RIGHT so với LEFT

Tôi đã thấy một số nhầm lẫn về những gì quan trọng trong việc xác định RIGHT và LEFT trong cú pháp kết hợp ngầm định.

THAM GIA BÊN NGOÀI TRÁI

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

THAM GIA ĐÚNG

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

Tất cả những gì tôi đã làm là hoán đổi các bên của các điều khoản trong mệnh đề WHERE, nhưng chúng vẫn tương đương về mặt chức năng. (Xem phần cao hơn trong câu trả lời của tôi để biết thêm thông tin về điều đó.) Vị trí của chữ (+)RIGHT hoặc LEFT xác định. (Cụ thể, nếu (+)ở bên phải, đó là THAM GIA TRÁI. Nếu (+)ở bên trái, đó là THAM GIA PHẢI.)


Các loại THAM GIA

Hai kiểu của JOIN là JOIN ngầm địnhJOIN rõ ràng . Chúng là các kiểu viết JOIN khác nhau, nhưng chúng tương đương nhau về mặt chức năng.

Xem câu hỏi SO này .

Tham gia ngầm chỉ đơn giản là liệt kê tất cả các bảng với nhau. Các điều kiện nối được chỉ định trong mệnh đề WHERE.

THAM GIA ngầm định

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

Các JOIN rõ ràng liên kết các điều kiện tham gia với việc bao gồm một bảng cụ thể thay vì trong mệnh đề WHERE.

THAM GIA rõ ràng

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

Các phép nối ngầm này có thể khó đọc và khó hiểu hơn, và chúng cũng có một số hạn chế vì các điều kiện kết hợp được trộn lẫn với các điều kiện WHERE khác. Do đó, các JOIN ngầm thường được khuyến nghị chống lại vì cú pháp rõ ràng.


3
Đúng rồi, tôi hiểu rồi - JOIN được tạo ngầm bởi sự hiện diện của dấu (+). Mát mẻ.
Kerrek SB,

2
@Mike: Đó là cách hoạt động của cú pháp +. Nó có nghĩa là "tùy chọn", vì vậy hãy đọc nó như "Liệt kê tất cả các bộ phận, tùy chọn để nhà cung cấp phù hợp".
Kerrek SB,

2
@Mike: Miễn là bạn biết những gì bạn đang chọn, nó không thực sự quan trọng bạn gọi nó như thế nào. Nhưng JOINthay vào đó , hãy làm ơn cho bản thân và sử dụng cú pháp thành ngữ ! Vậy thì không có chỗ cho sự nhầm lẫn.
Kerrek SB,

1
@TomJMuthirenthi Nếu không sử dụng FULL OUTER JOINcú pháp rõ ràng , bạn sẽ cần UNION [ALL]hai tập hợp kết quả cùng nhau: một cho A = B (+) và một cho B = A (+). Ví dụ trong câu hỏi này .
Wiseguy

1
Dấu "(+)" đi trên các cột của bảng tạo ra các dòng con null.
philipxy

9

Hai truy vấn đó đang hoạt động OUTER JOIN. Xem bên dưới

Oracle khuyên bạn nên sử dụng cú pháp mệnh đề FROM OUTER JOIN thay vì toán tử tham gia Oracle. Các truy vấn nối ngoài sử dụng toán tử tham gia Oracle (+) phải tuân theo các quy tắc và hạn chế sau, không áp dụng cho mệnh đề FROM cú pháp OUTER JOIN:

  • Bạn không thể chỉ định toán tử (+) trong một khối truy vấn cũng chứa cú pháp nối mệnh đề FROM.

  • Toán tử (+) chỉ có thể xuất hiện trong mệnh đề WHERE hoặc trong ngữ cảnh tương quan trái (khi chỉ định mệnh đề BẢNG) trong mệnh đề FROM và chỉ có thể được áp dụng cho một cột của bảng hoặc dạng xem.

  • Nếu A và B được nối bởi nhiều điều kiện nối, thì bạn phải sử dụng toán tử (+) trong tất cả các điều kiện này. Nếu bạn không làm như vậy, thì Cơ sở dữ liệu Oracle sẽ chỉ trả về các hàng kết quả từ một phép nối đơn giản, nhưng không có cảnh báo hoặc lỗi để cho bạn biết rằng bạn không có kết quả của một phép nối ngoài.

  • Toán tử (+) không tạo ra một phép nối ngoài nếu bạn chỉ định một bảng trong truy vấn bên ngoài và bảng khác trong một truy vấn bên trong.

  • Bạn không thể sử dụng toán tử (+) để tham gia bên ngoài một bảng với chính nó, mặc dù các liên kết tự là hợp lệ. Ví dụ, câu lệnh sau không hợp lệ:

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

    Tuy nhiên, tự tham gia sau là hợp lệ:

    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;
    
  • Toán tử (+) chỉ có thể được áp dụng cho một cột, không áp dụng cho một biểu thức tùy ý. Tuy nhiên, một biểu thức tùy ý có thể chứa một hoặc nhiều cột được đánh dấu bằng toán tử (+).

  • Một điều kiện WHERE có chứa toán tử (+) không thể được kết hợp với một điều kiện khác bằng cách sử dụng toán tử logic OR.

  • Điều kiện WHERE không thể sử dụng điều kiện so sánh IN để so sánh cột được đánh dấu bằng toán tử (+) với một biểu thức.

Nếu mệnh đề WHERE chứa điều kiện so sánh một cột từ bảng B với một hằng số, thì toán tử (+) phải được áp dụng cho cột để Oracle trả về các hàng từ bảng A mà nó đã tạo ra giá trị rỗng cho cột này. Nếu không thì Oracle chỉ trả về kết quả của một phép nối đơn giản.

Trong một truy vấn thực hiện các phép nối bên ngoài của hơn hai cặp bảng, một bảng có thể là bảng được tạo null chỉ cho một bảng khác. Vì lý do này, bạn không thể áp dụng toán tử (+) cho các cột B trong điều kiện nối cho A và B và điều kiện nối cho B và C. Hãy tham khảo SELECT để biết cú pháp cho phép nối ngoài.

Lấy từ http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm


3

Tôi đã thấy một số mâu thuẫn trong các câu trả lời ở trên, tôi vừa thử cách sau trên Oracle 12c và kết quả sau là chính xác:

THAM GIA BÊN NGOÀI TRÁI

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

THAM GIA ĐÚNG

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

0

THAM GIA BÊN NGOÀI TRÁI

CHỌN * TỪ A, B WHERE A.column = B.column (+)

THAM GIA ĐÚNG

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


-2

Có một số thông tin không chính xác trong chủ đề này. Tôi đã sao chép và dán thông tin không chính xác:

THAM GIA BÊN NGOÀI TRÁI

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

THAM GIA ĐÚNG

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

Ở trên là SAI !!!!! Nó trái ngược. Cách tôi xác định nó không chính xác là từ cuốn sách sau:

Oracle OCP Giới thiệu về Oracle 9i: Hướng dẫn thi SQL . Trang 115 Bảng 3-1 có một bản tóm tắt tốt về điều này. Tôi không thể hiểu tại sao SQL đã chuyển đổi của tôi không hoạt động bình thường cho đến khi tôi đi học cũ và xem trong một cuốn sách đã in!

Đây là phần tóm tắt từ cuốn sách này, được sao chép từng dòng:

Cú pháp tham gia bên ngoài Oracle:

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

Tương đương ANSI / ISO:

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

Lưu ý ở đây rằng nó là mặt trái của những gì được đăng ở trên. Tôi cho rằng cuốn sách này có thể có errata, tuy nhiên tôi tin tưởng cuốn sách này hơn những gì trong chủ đề này. Đó là một hướng dẫn thi để khóc thành tiếng ...


4
Điều này mâu thuẫn với những gì tôi đã liên kết trong câu trả lời của mình, đó là một đoạn trích từ Cơ sở dữ liệu Oracle 10g SQL (Osborne ORACLE Press Series) ấn bản đầu tiên (ngày 20 tháng 2 năm 2004), nêu rõ: "Trong một phép nối ngoài bên trái, toán tử phép nối ngoài thực sự được bật quyền của nhà điều hành bình đẳng. " Đây là một bản demo của ví dụ của bạn . Kết quả a.col_1(+) = b.col_1trận đấu THAM GIA PHẢI, không THAM GIA TRÁI.
Wiseguy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.