2009-07-28 97 views
68

使用oracle的加號表示法(+)與ANSI標準join表示法有什麼區別?Oracle的加號(+)表示法和ansi JOIN表示法之間的區別?

性能有差異嗎?

是否不贊成加號?

+37

(+)很難理解:) – 2009-07-28 12:11:14

+1

請參閱[外部連接Oracle vs ANSI語法](http://lalitkumarb.wordpress.com/2015/08/12/outer-joins-oracle-vs- ansi-syntax /) – 2015-08-12 10:14:17

回答

96

AFAIK「只用Oracle SQL支持」中,(+)符號只存在向後兼容性,因爲Oracle的ANSI標準之前推出它聯接被提到位。這是Oracle特有的,如果存在等效的符合標準的版本,則應避免在新代碼中使用它。

編輯:似乎有兩者之間的差異,以及(+)符號具有的ANSI連接語法沒有限制。 Oracle自己建議您不要使用(+)表示法。 全面介紹這裏的Oracle® Database SQL Language Reference 11g Release 1 (11.1)

Oracle建議您使用FROM條款OUTER JOIN語法,而不是甲骨文加入經營者。外連接是使用Oracle聯接運算符(+)受到以下規則和限制,這並不適用於FROM條款OUTER JOIN語法查詢:

  • 不能在查詢塊也包含FROM指定(+)操作子句連接語法。
  • (+)運算符只能出現在WHERE子句中,或者在FROM子句中的左相關(在指定TABLE子句時)中出現,並且只能應用於表或視圖的列。
  • 如果A和B由多個連接條件連接,那麼在所有這些條件中必須使用(+)運算符。如果您不這樣做,那麼Oracle數據庫將只返回由簡單連接產生的行,但沒有警告或錯誤,通知您沒有外部連接的結果。

  • 如果您在外部查詢中指定一個表,並且在內部查詢中指定另一個表,則(+)運算符不會生成外部聯接。

  • 儘管自連接有效,但不能使用(+)運算符將表外連接到自身。

例如,下面的語句是無效的:

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; 
  • (+)操作只能應用於到一列,而不是任意表達。但是,任意表達式可以包含一個或多個用(+)運算符標記的列。

  • A WHERE包含(+)運算符的條件不能與使用邏輯運算符OR的其他條件組合。

  • A WHERE條件不能使用IN比較條件將標有(+)運算符的列與表達式進行比較。

如果WHERE子句包含比較來自表B中以恆定的,則(+)操作者一列,以便Oracle返回從表A中對於其產生空值的行必須被施加到列中的條件爲此專欄。否則,Oracle只返回簡單連接的結果。

在執行多於兩對錶的外連接的查詢中,單個表可以是僅生成一個其他表的空生成表。因此,在A和B的連接條件以及B和C的連接條件中,不能將(+)運算符應用於B的列。有關外部連接的語法,請參閱SELECT

+0

謝謝。很好的解釋 – M3rlino 2010-11-23 09:27:01

+0

docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm – 2015-04-17 08:21:33

12

從Oracle 10開始,我仍然支持該表示法(我相信11)。它的使用被認爲是「老式的」,並且不像ANSI JOIN語法那樣可移植數據庫。它也被認爲具有更低的可讀性,但是如果你來自習慣於ANSI JOIN的+背景,則可能需要一點時間。在向Oracle投擲磚塊之前要了解的重要一點是,他們在ANSI委員會完成連接的定義之前開發了它們的+語法。

沒有性能差異;他們正在表達同樣的事情。

編輯:通過「不作爲便攜式」我應該說

+11

但請注意,當使用ANSI語法時,Oracle優化程序生成了不正確的查詢計劃或錯誤的結果時,出現了一些錯誤。這在11.1中比在10.1或10.2中少見得多,但它經常發生並且足以燒燬那些早期採用ANSI語法的人,使得大部分Oracle社區都不願意接受ANSI語法。 – 2009-07-28 14:46:26

+5

我有一個例子,你仍然不得不使用舊的Oracle連接語法:如果你用'FAST REFRESH'創建'MATERIALIZED VIEW',你不能使用ANSI語法。我剛剛查看了Oracle網頁的這個問題,它仍然存在。 Oracle不認爲這是一個錯誤!如果您有權訪問Oracle支持,請參閱Oracle Doc ID 1372720.1以瞭解詳細信息。 – 2014-01-22 11:49:26

12

我同意託尼·米勒的答案,並想補充一點,還有幾件事情,你不能用(+)synthax做:

  • 不能FULL OUTER JOIN兩個表,你必須用一個UNION ALL兩個連接做手工,
  • 你不能OUTER JOIN表到兩個或多個表,你必須手動創建一個子查詢(即:b.id = a.id (+) AND c.id = a.id (+)不是一個可接受的條款)
+0

外鏈怎麼樣加入類似這樣的'a.b_id = b.id(+)AND b.c_id = c.id(+)''我繼承了類似的東西,並且如果'a'' b'連接出現,我懷疑真正返回的結果爲null – Dan 2014-02-05 17:08:31

+0

@Dan您可以鏈接「舊樣式」外連接'A - > B - > C'沒有問題。與標準ANSI連接相同的規則適用:如果其中一個鏈接是常規連接,則外部連接鏈會中斷。換句話說,'LEFT JOIN B INNER JOIN C'等於'A JOIN B JOIN C'。 – 2014-02-05 17:53:16

1

Oracle(+)nota僅在Oracle中使用,這是供應商特定的。並且,ANSI標準加入符號可以是用於任何RDBMS(如Sql Server,MySql等)。否則,Oracle(+)符號和ANSI standared Join符號之間沒有區別。

如果您在SQL查詢中使用ANSI標準加入符號,則可以在任何RDBMS中使用相同的查詢。而且,如果你是移植到你的數據庫從Oracle到任何其他RDBMS在這種情況下,你必須使用ANSI語法

1

我使用(+)符號,因爲幾乎所有與Oracle Apps r12相關的查詢都基於此。我還沒有在Oracle APPS查詢中看到帶有標準「連接」表達式的單個SQL查詢(甚至是Oracle本身提供的查詢)。如果你不相信我,只需要谷歌任何與Oracle應用相關的信息。例如:Fixed assets related queries

9

最全面的答案顯然是nagul

加法爲那些誰正在尋找快速轉換/映射到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

其中一個很好的理由使用ANSI語法在舊的Oracle連接語法是,沒有機會偶然創建笛卡爾產品。有了更多數量的表格,就有機會錯過隱含的與較舊的Oracle連接語法的連接,但是,使用ANSI語法,您不能錯過任何連接,因爲您必須明確地提示它們

Oracle外連接語法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 -

在11gR1中的原生支持的散列全外連接的前,Oracle會在內部進行轉換t時的FULL OUTER JOIN通過以下方式 -

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); 

看一看this

1
  1. 使用顯式JOIN而不是隱式(無論它們是否是外連接)是因爲使用隱式連接意外創建笛卡爾積更容易。有了明確的JOIN,你不能「不小心」創建一個JOIN。涉及的表越多,風險就越高,因此您錯過了一個連接條件。
  2. 與ANSI加入相比,基本上(+)嚴格限制。此外,它僅在Oracle中可用,而ANSI加入語法由所有主要DBMS支持。
  3. SQL在遷移到ANSI語法後不會開始執行得更好 - 它只是不同的語法。
  4. Oracle強烈建議您使用前一示例中顯示的更靈活的FROM子句連接語法。過去有一些ANSI語法的錯誤,但是如果你使用最新的11.2或12.1版本,應該已經修復了。
  5. 使用JOIN運算符可確保您的SQL代碼符合ANSI標準,從而可以更輕鬆地將前端應用程序移植到其他數據庫平臺。
  6. 連接條件在每個表上具有非常低的選擇性並且對理論交叉乘積中的元組具有高選擇性。 where語句中的條件通常具有更高的選擇性。
  7. Oracle在內部將ANSI語法轉換爲(+)語法,您可以在執行計劃的謂詞信息部分看到這一點。
相關問題