最近在修改數據庫存儲過程時,出現了一個ORA-00933
錯誤,
執行的是 INSERT INTO...SELECT 語句,具體語句如下:
INSERT INTO BASP_DX.QLR@GT(BDCDYH, QSZT)
SELECT NVL(e.BDCDYH, ' '), b.LIFECYCLE AS QSZT
FROM DJ_DY as
LEFT JOIN DJ_XGDJGL d
ON d.ZSLBH = a.SLBH
LEFT JOIN DJ_DJB e
ON e.SLBH = d.FSLBH
AND e.SLBH = '0123456789'
LEFT JOIN DJ_QLRGL f
ON f.SLBH = e.SLBH
AND f.QLRLX = '權利人'
LEFT JOIN DJ_QLRGL b
ON b.SLBH = a.SLBH
AND (b.QLRLX = '抵押權人' OR (b.QLRLX = '抵押人' AND b.QLRID = f.QLRID))
WHERE a.SLBH = '20170318'
AND e.SLBH IS NOT NULL
AND b.QLRID IS NOT NULL
AND (a.LIFECYCLE = '0' OR a.LIFECYCLE IS NULL);
沒毛病啊!!!谷狗上得來一篇文章
說造成ORA-00933
的可能原因有:
- 使用了含有
ORDER BY
或INNER JOIN
子句的INSERT
語句 - 使用了含有
ORDER BY
或INNER JOIN
子句的DELETE
語句 - 使用了含有
INNER JOIN
子句的UPDATE
語句
然鵝,我的語句都沒有啊!!!但是這給了我靈感,
會不會是JOIN
后面的條件太多了被當成INNER JOIN
(沒錯,就是瞎猜的,腦洞大沒辦法~~~)
於是乎,我就傻里傻氣的開始注釋LEFT JOIN
后的條件,
當我注釋掉AND (b.QLRLX = '抵押權人' OR (b.QLRLX = '抵押人' AND b.QLRID = f.QLRID))
時,奇跡發生了,不報錯了(當然,一下子插入了幾千條,嚇得小生鼠標都掉了),
接着,我將條件放到WHERE
語句后面,成了如下形式:
INSERT INTO BASP_DX.QLR@GT(BDCDYH, QSZT)
SELECT NVL(e.BDCDYH, ' '), b.LIFECYCLE AS QSZT
FROM DJ_DY as
LEFT JOIN DJ_XGDJGL d
ON d.ZSLBH = a.SLBH
LEFT JOIN DJ_DJB e
ON e.SLBH = d.FSLBH
AND e.SLBH = '0123456789'
LEFT JOIN DJ_QLRGL f
ON f.SLBH = e.SLBH
AND f.QLRLX = '權利人'
LEFT JOIN DJ_QLRGL b
ON b.SLBH = a.
-- 條件原來在這里
WHERE a.SLBH = '20170318'
AND e.SLBH IS NOT NULL
-- LEFT JOIN后的條件移動到了這里
AND (b.QLRLX = '抵押權人' OR (b.QLRLX = '抵押人' AND b.QLRID = f.QLRID))
AND (a.LIFECYCLE = '0' OR a.LIFECYCLE IS NULL);
這樣便可以運行成功,但是...這是為什么啊!!!Tell me Why???
最后小生想到了我大StackOverFlow,趕快上去提了個問題。
經高人點撥,是一種叫做Triangular Join
的東西導致的,
大致就是說語句里面有自連接(如上例中的DJ_XGDJGL
分別被命名為b
和f
做了關聯),
但是這並沒有關系,關鍵是這個自連接的條件里面不能有涉及自連接表的字段進行比較,
(上例中的b.QLRID = f.QLRID
就不符合這一點,所以執行失敗,嘗試了一下移除這個條件,
便可以執行了)
總結
會造成ORA-00933
的原因分為三種:
- 使用了含有
ORDER BY
或INNER JOIN
子句的INSERT
、DELETE
語句 - 使用了含有
INNER JOIN
子句的UPDATE
語句 - 使用了條件中含有自連接表字段比較的
Triangular Join
參考鏈接:
http://www.databasestar.com/ora-00933/
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:4549764300346084350