2009-07-28 3 views
68

Sự khác nhau giữa việc sử dụng ký hiệu cộng hoặc ký hiệu (+) qua tiêu chuẩn ansi tiêu chuẩn join là gì?Sự khác biệt giữa ký hiệu cộng (+) của Oracle và ký hiệu ansi JOIN?

Có sự khác biệt về hiệu suất không?

Ký hiệu cộng không được chấp nhận?

+37

(+) khó hiểu hơn :) –

+1

Xem [Tham gia Oracle và cú pháp ANSI của Oracle] (http://lalitkumarb.wordpress.com/2015/08/12/outer-joins-oracle-vs- Ansi-syntax /) –

Trả lời

96

AFAIK, các ký hiệu (+) chỉ xuất hiện để tương thích ngược vì Oracle ra mắt nó trước khi các tiêu chuẩn ANSI cho tham gia được đưa tại chỗ. Nó đặc trưng cho Oracle và bạn nên tránh sử dụng nó trong mã mới khi có sẵn một phiên bản tương đương với tiêu chuẩn tương đương.

Chỉnh sửa:Dường như có sự khác biệt giữa hai ký hiệu và ký hiệu (+) có các hạn chế mà cú pháp nối ANSI không có. Bản thân Oracle khuyên bạn không nên sử dụng ký hiệu (+). Mô tả đầy đủ ở đây Oracle® Database SQL Language Reference 11g Release 1 (11.1):

Oracle khuyến cáo rằng bạn sử dụng cú pháp FROM khoản OUTER JOIN chứ không phải là Oracle tham gia điều hành. Bên ngoài tham gia truy vấn sử dụng Oracle tham gia điều hành (+) phải tuân thủ các quy tắc sau đây và những hạn chế, mà không áp dụng cho các FROM khoản OUTER JOIN cú pháp:

  • Bạn không thể chỉ định các nhà điều hành (+) trong một khối truy vấn mà cũng chứa FROM cú pháp nối mệnh đề.
  • Nhà điều hành (+) chỉ có thể xuất hiện trong mệnh đề WHERE hoặc trong ngữ cảnh tương quan bên trái (khi chỉ định mệnh đề TABLE) trong mệnh đề FROM và chỉ có thể được áp dụng cho cột của bảng hoặc chế độ xem.
  • Nếu A và B được nối với nhau bằng nhiều điều kiện kết 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 không, 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 để thông báo cho bạn 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 kết nối bên 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 truy vấn bên trong.

  • Bạn không thể sử dụng toán tử (+) để tự động tham gia vào một bảng, mặc dù tự động tham gia hợp lệ.

Ví dụ, báo cáo kết quả sau đây là không hợp lệ:

SELECT employee_id, manager_id 
FROM employees 
WHERE employees.manager_id(+) = employees.employee_id; 

Tuy nhiên, tự sau đây tham gia 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; 
  • Nhà điều hành (+) thể được áp dụng chỉ vào một cột, không phải 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ử (+).

  • A WHERE điều kiện chứa toán tử (+) không thể kết hợp với đ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 với toán tử (+) có biểu thức.

Nếu mệnh đề WHERE chứa một điều kiện so sánh một cột từ bảng B với một hằng số, sau đó các nhà điều hành (+) phải được áp dụng cho các cột sao cho Oracle trả về các hàng từ bảng A mà nó đã tạo ra null 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 truy vấn thực hiện các kết nối bên ngoài của nhiều hơn hai cặp bảng, một bảng có thể là bảng được tạo không có giá trị cho chỉ 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 của B trong điều kiện kết 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.

+0

Cảm ơn bạn. Giải thích tốt – M3rlino

+0

docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm –

12

Ký pháp vẫn được hỗ trợ như của Oracle 10 (và tôi tin 11). Việc sử dụng nó được coi là "lỗi thời" và cũng không phải là cơ sở dữ liệu di động như cú pháp ANSI JOIN. Nó cũng được coi là ít dễ đọc hơn, mặc dù nếu bạn đến từ nền + nhận được sử dụng để ANSI JOIN có thể mất một ít thời gian. Điều quan trọng cần biết trước khi ném brickbats tại Oracle là họ đã phát triển cú pháp + của họ trước khi ủy ban ANSI đã hoàn thành các định nghĩa cho các phép nối.

Không có sự khác biệt về hiệu suất; họ đang thể hiện cùng một điều.

Edit: Bằng cách "không phải là di động" Lẽ ra tôi nên nói "chỉ được hỗ trợ trong Oracle SQL"

+11

Hãy nhận biết, mặc dù, đã có một số lỗi mà trình tối ưu hóa Oracle đã tạo ra các kế hoạch truy vấn sai hoặc kết quả không chính xác khi cú pháp ANSI được sử dụng. Điều này ít phổ biến hơn trong 11,1 so với 10,1 hoặc 10,2, nhưng nó đã xảy ra thường xuyên và đốt cháy đủ người đã sớm chấp nhận cú pháp ANSI rằng phần lớn của cộng đồng Oracle đang do dự để nắm lấy cú pháp ANSI. –

+5

Tôi có một ví dụ trong đó bạn vẫn bị buộc phải sử dụng cú pháp tham gia Oracle cũ: Nếu bạn tạo một khung nhìn MATERIALIZED' với 'FAST REFRESH' bạn không thể sử dụng cú pháp ANSI. Tôi chỉ cần kiểm tra trang Oracle cho vấn đề này, nó vẫn còn hiện diện. Oracle không coi đây là lỗi! Xem Oracle Doc ID 1372720.1 để biết chi tiết, trong trường hợp bạn có quyền truy cập vào Hỗ trợ Oracle. –

12

Tôi đồng ý với câu trả lời Tony Miller và muốn thêm rằng cũng có một vài điều mà bạn không thể làm bằng dấu (+) synthax:

  • Bạn không thể FULL OUTER JOIN hai bảng, bạn phải làm điều đó bằng tay với một UNION ALL của hai tham gia,
  • bạn không thể OUTER JOIN một bảng để hai hoặc nhiều bảng, bạn phải tự tạo một subquery (ví dụ: b.id = a.id (+) AND c.id = a.id (+) không phải là một khoản chấp nhận được)
+0

Điều gì về một chuỗi bên ngoài tham gia một cái gì đó như thế này, 'a.b_id = b.id (+) AND b.c_id = c.id (+) 'Tôi thừa hưởng một cái gì đó như thế và tôi hỏi những gì thực sự được trả lại nếu' a' 'b' tham gia đi lên null – Dan

+0

@Dan Bạn có thể chuỗi" kiểu cũ "bên ngoài tham gia' A -> B -> C' mà không có vấn đề. Các quy tắc tương tự như các tham gia ANSI tiêu chuẩn áp dụng: Một chuỗi các phép nối ngoài bị hỏng nếu một trong các liên kết của nó là một phép nối thường xuyên. Nói cách khác 'TÊN THAM GIA B BÊN ĐỐI TÁC B' tương đương với 'A JOIN B JOIN C'. –

1

Oracle (+) nota tion chỉ được sử dụng trong Oracle, là nhà cung cấp cụ thể. Và, ANSI standared Tham gia ký hiệu có thể là được sử dụng trong bất kỳ RDBMS nào (như Sql Server, MySql, v.v.). Nếu không, không có sự khác biệt giữa ký hiệu Oracle (+) và ký hiệu tham gia ANSI.

Nếu bạn đang sử dụng ký hiệu tham gia độc lập ANSI trong truy vấn Sql của mình, bạn có thể sử dụng cùng một truy vấn trong bất kỳ RDBMS nào. Và, nếu bạn đang porting cơ sở dữ liệu của bạn từ Oracle đến bất kỳ RDBMS khác trong điều kiện đó, bạn phải sử dụng ANSI Cú pháp.

1

Tôi sử dụng ký hiệu (+), vì gần như tất cả các truy vấn liên quan đến Oracle Apps r12 đều dựa trên đó. Tôi đã không nhìn thấy một truy vấn SQL duy nhất với một biểu thức "nối" tiêu chuẩn trong các truy vấn Oracle APPS (ngay cả những truy vấn được cung cấp bởi chính Oracle). Nếu bạn không tin tôi, chỉ cần google bất kỳ thông tin liên quan đến ứng dụng Oracle nào. Ví dụ: Fixed assets related queries

9

Câu trả lời toàn diện nhất rõ ràng là câu trả lời là nagul.

Một sự bổ sung cho những ai đang tìm kiếm dịch nhanh/ánh xạ tới cú pháp ANSI:

-- 
-- INNER JOIN 
-- 
SELECT * 
FROM EMP e 
INNER JOIN DEPT d ON d.DEPTNO = e.DEPTNO; 

-- Synonym in deprecated oracle (+) syntax 
SELECT * 
FROM EMP e, 
    DEPT d 
WHERE d.DEPTNO = e.DEPTNO; 

-- 
-- LEFT OUTER JOIN 
-- 
SELECT * 
FROM EMP e 
LEFT JOIN DEPT d ON d.DEPTNO = e.DEPTNO; 

-- Synonym in deprecated oracle (+) syntax 
SELECT * 
FROM EMP e, 
    DEPT d 
WHERE d.DEPTNO (+) = e.DEPTNO; 

-- 
-- RIGHT OUTER JOIN 
-- 
SELECT * 
FROM EMP e 
RIGHT JOIN DEPT d ON d.DEPTNO = e.DEPTNO; 

-- Synonym in deprecated oracle (+) syntax 
SELECT * 
FROM EMP e, 
    DEPT d 
WHERE d.DEPTNO = e.DEPTNO(+); 

-- 
-- CROSS JOIN 
-- 
SELECT * 
FROM EMP e 
CROSS JOIN DEPT d; 

-- Synonym in deprecated oracle (+) syntax 
SELECT * 
FROM EMP e, 
    DEPT d; 

-- 
-- FULL JOIN 
-- 
SELECT * 
FROM EMP e 
FULL JOIN DEPT d ON d.DEPTNO = e.DEPTNO; 

-- Synonym in deprecated oracle (+) syntax !NOT WORKING! 
SELECT * 
FROM EMP e, 
    DEPT d 
WHERE d.DEPTNO (+) = e.DEPTNO(+); 
1

Một trong những lý do tốt để sử dụng ANSI cú pháp trên cái cũ Oracle gia nhập cú pháp là, có vô số cơ hội vô tình tạo ra một sản phẩm hàng hóa cartesian. Với số lượng bảng nhiều hơn, có một cơ hội để bỏ lỡ ngầm định tham gia với cú pháp tham gia Oracle cũ hơn, tuy nhiên, với cú pháp ANSI bạn không thể bỏ lỡ bất kỳ tham gia nào khi bạn phải rõ ràng đề cập đến chúng.

Sự khác biệt giữa Cú pháp nối ngoài OracleCú pháp ANSI/ISO.

LEFT OUTER JOIN -

SELECT e.last_name, 
    d.department_name 
FROM employees e, 
    departments d 
WHERE e.department_id = d.department_id(+); 

SELECT e.last_name, 
    d.department_name 
FROM employees e 
LEFT OUTER JOIN departments d 
ON (e.department_id = d.department_id); 

RIGHT OUTER JOIN -

SELECT e.last_name, 
    d.department_name 
FROM employees e, 
    departments d 
WHERE e.department_id(+) = d.department_id; 

SELECT e.last_name, 
    d.department_name 
FROM employees e 
RIGHT OUTER JOIN departments d 
ON (e.department_id = d.department_id); 

FULL OUTER JOIN -

Trước sự ủng hộ mẹ đẻ của băm outerjoin đầy đủ trong 11gR1 , Oracle sẽ hội tụ nội bộ T FULL OUTER JOIN theo cách sau -

SELECT e.last_name, 
    d.department_name 
FROM employees e, 
    departments d 
WHERE e.department_id = d.department_id(+) 
UNION ALL 
SELECT NULL, 
    d.department_name 
FROM departments d 
WHERE NOT EXISTS 
    (SELECT 1 FROM employees e WHERE e.department_id = d.department_id 
); 

SELECT e.last_name, 
    d.department_name 
FROM employees e 
FULL OUTER JOIN departments d 
ON (e.department_id = d.department_id); 

Hãy xem this.

1
  1. Sử dụng JOIN rõ ràng hơn là ẩn (bất kể chúng có tham gia bên ngoài hay không) là dễ dàng hơn khi vô tình tạo ra sản phẩm Descartes với các kết nối ngầm định. Với JOIN JOINs bạn không thể "do tai nạn" tạo ra một. Càng có nhiều bảng có liên quan đến nguy cơ cao hơn là bạn bỏ lỡ một điều kiện tham gia.
  2. Về cơ bản (+) bị giới hạn nghiêm trọng so với tham gia ANSI. Hơn nữa nó chỉ có sẵn trong Oracle trong khi cú pháp nối ANSI được hỗ trợ bởi tất cả các DBMS lớn
  3. SQL sẽ không bắt đầu hoạt động tốt hơn sau khi di chuyển sang cú pháp ANSI - nó chỉ khác cú pháp.
  4. Oracle mạnh mẽ khuyên bạn nên sử dụng cú pháp nối khoản FROM linh hoạt hơn được hiển thị trong ví dụ trước. Trong quá khứ đã có một số lỗi với cú pháp ANSI nhưng nếu bạn đi với 11,2 hoặc 12,1 mới nhất mà nên được cố định rồi.
  5. Sử dụng toán tử JOIN đảm bảo mã SQL của bạn tuân thủ ANSI và do đó sẽ cho phép ứng dụng đầu cuối dễ dàng được chuyển sang các nền tảng cơ sở dữ liệu khác.
  6. Tham gia các điều kiện có độ chọn lọc rất thấp trên mỗi bảng và tính chọn lọc cao trên các bộ dữ liệu trong sản phẩm chéo lý thuyết. Các điều kiện trong câu lệnh where thường có độ chọn lọc cao hơn nhiều.
  7. Oracle nội bộ chuyển đổi cú pháp ANSI thành cú pháp (+), bạn có thể thấy điều này xảy ra trong phần Thông tin dự đoán của kế hoạch thực hiện.