Oracle

根據子表中的條件刪除父表中的行 - Oracle

  • September 11, 2013

我有一個B帶有外鍵的表 table A。我想DELETE在表中的一些行B,我也想DELETE在表中他們的父行A。但是,刪除條件基於 table BA不能先刪除表中的行,因為表中的引用B限制了刪除,但我還必須A從行中獲取要刪除的鍵B

這是一個帶有範例表結構的 SQLFiddle: http ://sqlfiddle.com/#!4/f156c/4/0 。

我的第一個傾向是嘗試通過將鍵SELECT從 from中保存B到變數中,然後將其用於DELETEfrom A

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錯誤。錯誤本身來自DELETEon A; 我知道這一點,因為如果我將其註釋掉,該塊就會執行。

我怎樣才能繞過這個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進行測試**

有關 Oracle 文件中的約束的更多詳細資訊:約束管理完整性約束

引用自:https://dba.stackexchange.com/questions/49634