根據子表中的條件刪除父表中的行 - Oracle
我有一個
B
帶有外鍵的表 tableA
。我想DELETE
在表中的一些行B
,我也想DELETE
在表中他們的父行A
。但是,刪除條件基於 tableB
。A
不能先刪除表中的行,因為表中的引用B
限制了刪除,但我還必須A
從行中獲取要刪除的鍵B
。這是一個帶有範例表結構的 SQLFiddle: http ://sqlfiddle.com/#!4/f156c/4/0 。
我的第一個傾向是嘗試通過將鍵
SELECT
從 from中保存B
到變數中,然後將其用於DELETE
fromA
。DECLARE A_ID_TO_DELETE DBMS_SQL.NUMBER_TABLE; BEGIN SELECT A_ID BULK COLLECT INTO A_ID_TO_DELETE FROM (SELECT A_ID FROM B WHERE LENGTH(B_DATA) > 4 ); DELETE FROM B WHERE LENGTH(B_DATA) > 4; DELETE FROM A WHERE A_ID IN A_ID_TO_DELETE; END; /
但這只會給出一個
PLS-00382: expression is of wrong type
錯誤。錯誤本身來自DELETE
onA
; 我知道這一點,因為如果我將其註釋掉,該塊就會執行。我怎樣才能繞過這個
expression is of wrong type
錯誤,或者有什麼方法可以解決這個問題?Oracle 版本:Oracle 數據庫 10g 企業版版本 10.2.0.1.0 - 產品
(是的,我很清楚那有多大。客戶選擇的數據庫,而不是我們的。)
像這樣試試
DECLARE A_ID_TO_DELETE DBMS_SQL.NUMBER_TABLE; BEGIN SELECT A_ID BULK COLLECT INTO A_ID_TO_DELETE FROM (SELECT A_ID FROM B WHERE LENGTH(B_DATA) > 4 ); DELETE FROM B WHERE LENGTH(B_DATA) > 4; FORALL i IN A_ID_TO_DELETE.first..A_ID_TO_DELETE.last DELETE FROM A WHERE A_ID = A_ID_TO_DELETE(i); END; /
Oracle 中的外鍵約束被定義為(預設情況下),
NON DEFERRABLE
這意味著始終在語句末尾檢查約束。還有另外兩種定義約束的方法:
DEFERRABLE INITIALLY DEFERRED
如果您將約束定義(或現在修改)為
DEFERRABLE INITIALLY DEFERRED
,那麼約束的檢查將在事務結束時進行。所以,這對你有用(但它也會修改約束在所有其他事務中的檢查方式。)
DEFERRABLE INITIALLY IMMEDIATE
如果您將其定義為
DEFERRABLE
(它獲得預設值INITIALLY IMMEDIATE
),那麼它仍會在語句末尾進行檢查,但可以推遲。因此,您可以選擇在事務中設置所有約束SET CONSTRAINTS ALL DEFERRED;
,這樣可以正常工作:SET CONSTRAINTS ALL DEFERRED; DELETE FROM A WHERE A_ID IN ( SELECT A_ID FROM B WHERE LENGTH(B_DATA) > 4 ); DELETE FROM B WHERE LENGTH(B_DATA) > 4;
在**SQL-Fiddle進行測試**