我們都知道,PL/SQL中實現外連接,除了可以用關鍵詞OUTER JOIN外,還可以用Oracle的外連接符號(+)。對於這個外連接符號(+),雖然看到書上說:使用(+)進行外連接時,where條件中,對於附表的字段都應帶上(+)。但在實際應用中,發現對它的理解還遠遠不夠。現在結合實際的SQL語句,讓我們再仔細地瞧瞧這個(+)的"真面目"吧。
首先,我們來看一下Oralce的《SQL Reference》對它的一點說明。
—————————————————————————————————————
If the WHERE clause contains a condition that compares a column from table B with a
constant, then the (+) operator must be applied to the column so that Oracle returns
the rows from table A for which it has generated nulls for this column. Otherwise
Oracle returns only the results of a simple join.
注:table A爲主表,table B爲附表。
—————————————————————————————————————
現在有以下兩張表:
表A 員工(EMPLOYEE)
|
EMP_NO |
EMP_NAME |
JOB |
DEPT_NO |
1 |
1 |
HXF |
PRESIDENT |
2 |
2 |
2 |
SCOTT |
CLERK |
1 |
3 |
3 |
SMITH |
SALESMAN |
3 |
4 |
4 |
JOHN |
MANAGER |
|
表B 部門(DEPARTMENT)
|
DEPT_NO |
DEPT_NAME |
LOCATION |
DEL_FLG |
1 |
1 |
ACCOUNTING |
HANGZHOU |
0 |
2 |
2 |
RESEARCH |
BEIJING |
0 |
3 |
3 |
OPERATIONS |
SHANGHAI |
1 |
其中部門表中字段DEL_FLG爲0表示該條記錄已刪除,是無效記錄;反之相反。
如果需要找出表A中的所有記錄,並關聯上表B中的有效記錄,我們很可能會寫出以下三種SQL語句:
語句一:
SELECT A.EMP_NAME, A.JOB, B.*
FROM EMPLOYEE A, DEPTMENT B
WHERE A.DEPT_NO = B.DEPT_NO(+)
AND B.DEL_FLG(+) = '0'
該語句利用Oracle的外連接符號,並用條件B.DEL_FLG(+) = '0'限定表B種的有效記錄。也有人可能會寫成語句二:
語句二:
SELECT A.EMP_NAME, A.JOB, B.*
FROM EMPLOYEE A, DEPTMENT B
WHERE A.DEPT_NO = B.DEPT_NO(+)
AND B.DEL_FLG = '0'
語句二中表B中的字段DEL_FlG沒帶外連接符號。還有種寫法,如語句三:
語句三:
SELECT *
FROM (SELECT A.EMP_NAME, A.JOB, B.*
FROM EMPLOYEE A, DEPTMENT B
WHERE A.DEPT_NO = B.DEPT_NO(+))
WHERE DEL_FLG IS
NULL
OR DEL_FLG = '0'
該語句首先將表A和表B通過外連接關聯起來,然後對錶B中的字段DEL_FlG進行限定,因爲要關
聯表B中的有效字段,所以有條件DEL_FLG = '0',又因爲是左連接,所以會有結果集中表B的記錄爲空的情況,所以又加上條件DEL_FLG IS NULL。
粗粗看起來,以上三種SQL語句的寫法都有道理,沒有問題。那我們再來看下它們的執行結果:
語句一的執行結果
|
EMP_NAME |
JOB |
DEPT_NO |
DEPT_NAME |
LOCATION |
DEL_FLG |
1 |
SCOTT |
CLERK |
1 |
ACCOUNTING |
HANGZHOU |
0 |
2 |
HXF |
PRESIDENT |
2 |
RESEARCH |
BEIJING |
0 |
3 |
JOHN |
MANAGER |
|
|
|
|
4 |
SMITH |
SALESMAN |
|
|
|
|
語句二的執行結果
|
EMP_NAME |
JOB |
DEPT_NO |
DEPT_NAME |
LOCATION |
DEL_FLG |
1 |
HXF |
PRESIDENT |
2 |
RESEARCH |
BEIJING |
0 |
2 |
SCOTT |
CLERK |
1 |
ACCOUNTING |
HANGZHOU |
0 |
語句三的執行結果
|
EMP_NAME |
JOB |
DEPT_NO |
DEPT_NAME |
LOCATION |
DEL_FLG |
1 |
SCOTT |
CLERK |
1 |
ACCOUNTING |
HANGZHOU |
0 |
2 |
HXF |
PRESIDENT |
2 |
RESEARCH |
BEIJING |
0 |
3 |
JOHN |
MANAGER |
|
|
|
|
我們發現三條語句的執行結果截然不同。那到底哪一個是對的呢?
首先我們應該清楚,要求是以表A爲主表,表B爲附表的外連接,根據外連接的定義,就要求選出表A中的所有記錄,顯然語句二和三的結果就不符號這個要求。其次,我們要求選出表B中的有效記錄,出現在結果集中的表B的字段DEL_FLG的值只能是0。由此可見,語句一的執行結果是正確的。
那麼語句二和三是怎麼回事呢?在語句二中,雖然對兩張表中的相關字段進行了外連接,但是,對附表B中的字段DEL_FLG限定條件的時候,沒有使用外連接符號,導致這個連接變成了全連接。語句三的話,最具有迷惑性,表面看上去很有道理,但實際上它不是真正的外連接,
它把跟附表B中的無效記錄相關聯的表A中的記錄也排除在外了,這是不符號外連接要求的。最重要的是,我們要明白對於外連接,有主表和附表之分,主表中的記錄要全部選出,而附表中的記錄可有可無。