Oracle 9i前專有的(+)外連接語法雖已被ANSI LEFT/RIGHT/FULL OUTER JOIN取代,但存量系統大量存在。本文通過實戰代碼解析(+)的定位規則、多表連接限制、條件判斷陷阱,並提供標準化改寫模板。
(+)標記在從表(可為空側)的欄位上。A.col = B.col(+) 相當於 B LEFT JOIN A(B為主表,A為從表)。A.col(+) = B.col 相當於 A LEFT JOIN B(A為主表,B為從表)。(+),否則退化為內連接。(+)不能用於OR、IN、NOT IN、比較運算符!=等複雜條件。SELECT TO_CHAR(TBA.FBS_IO_DATE,'YYYY/MM/DD') A1,
TBA.TBA_TBD_NO A2,
TBB.TBB_NAME_S A3,
TBC.TBC_CHAR1 A4,
TBD.TBD_NAME A5
FROM SNTBATRN TBA,
ZMTBCMST TBC,
CMTBBMST TBB,
CMTBDMST TBD
WHERE TBA.TBA_KAI_CODE = 'XXX'
AND TBA.TBA_KESHI_KBN = '0'
AND TBA.TBA_TAISYO_KBN IN ('0','2')
AND TBB_KAI_CODE(+) = 'XXX'
AND TBB_BUN_CODE(+) = 'S001'
AND TBB_START_DATE <= SYSDATE
AND TBB_END_DATE >= SYSDATE
AND TBB.TBB_CODE(+) = TBA.TBA_STN_CODE
AND TBC.TBC_KAI_CODE(+) = 'XXX'
AND TBC.TBC_SUB_KBN(+) = 'SN'
AND TBD.TBD_KAI_CODE(+) = 'XXX'
AND TBD.TBD_CODE(+) = TBA.TBA_SNS_CODE;
解析:TBA為主表(駕馭端),TBB/TBC/TBD均為從表,所有從表欄位在JOIN條件與過濾條件上均加(+)。注意TBB_START_DATE <= SYSDATE等過濾條件也必須加(+),否則會過濾掉NULL擴展行。
SELECT TBA.TBA_1, TBB.TBB_1, TBC.TBC_1
FROM TBA,
(SELECT TBB_1, TBB_2 FROM TBB WHERE TBB_3 LIKE '%NEWWEAPON%') TBB,
TBC
WHERE TBA.TBA_A > 2
AND TBA.TBA_2 = TBB.TBB_2
AND TRIM(TBA.TBA_3) = TRIM(TBC.TBC_3(+));
要點:
① 子查詢結果集作為從表,外連接標記在主查詢的JOIN條件TBC.TBC_3(+)上。
② TRIM函數包裹的欄位同樣需在從表側加(+),寫法為TRIM(TBC.TBC_3(+))。
| 舊式(+) | ANSI標準 |
|---|---|
A.col = B.col(+) | FROM A LEFT JOIN B ON A.col = B.col |
A.col(+) = B.col | FROM B LEFT JOIN A ON A.col = B.col |
| 多表連續(+) | FROM A LEFT JOIN B ON ... LEFT JOIN C ON ... |
| 過濾條件帶(+) | LEFT JOIN B ON A.id = B.id AND B.status = 'ACTIVE' |
(+)出現位置,繪製主從表關係圖。LEFT JOIN (subquery) alias ON ...。NULL語義一致性:WHERE col IS NULL在ANSI中行為相同。徹底理解(+)的定位邏輯與限制,是老系統平滑遷移至標準SQL、消除技術債的關鍵一步。