代码之家  ›  专栏  ›  技术社区  ›  heymatthew

PostgreSQL“delerable Delete”仍然在删除时命中约束

  •  5
  • heymatthew  · 技术社区  · 15 年前

    我想从两个表中删除行,这两个表通过一组可延迟约束相互依赖。为了简化本文,我模拟了一个简单的DB模式。

    以下是两个表的说明:

    tab-quarantine=> \d delete_from_me
           Table "public.delete_from_me"
      Column   |       Type        | Modifiers 
    -----------+-------------------+-----------
     id        | character varying | not null
     extension | character varying | not null
    Indexes:
        "delete_from_me_pkey" PRIMARY KEY, btree (id)
    
    tab-quarantine=> \d constraining_table 
       Table "public.constraining_table"
     Column |       Type        | Modifiers 
    --------+-------------------+-----------
     image  | character varying | not null
     type   | character varying | not null
    Foreign-key constraints:
        "constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id)
             ON UPDATE CASCADE
             ON DELETE RESTRICT DEFERRABLE
    

    下面是一些我刚刚在里面罗列的样本数据:

    tab-quarantine=> SELECT * FROM delete_from_me;
         id     | extension 
    ------------+-----------
     12345abcde | png
    (1 row)
    
    tab-quarantine=> SELECT * FROM constraining_table;
       image    |   type   
    ------------+----------
     12345abcde | select_me
    (1 row)
    

    BEGIN;
    \set ON_ERROR_STOP 1
    SET CONSTRAINTS ALL DEFERRED;
    DELETE FROM delete_from_me WHERE id IN (
        SELECT image FROM constraining_table WHERE type = 'select_me'
    );
    DELETE FROM constraining_table WHERE type = 'select_me';
    COMMIT;
    

    此事务失败。当我单步执行并手动执行此操作时,将显示以下错误消息:

    ERROR:  update or delete on table "delete_from_me" violates foreign key constraint "constraining_table_image_fkey" on table "constraining_table"
    DETAIL:  Key (id)=(12345abcde) is still referenced from table "constraining_table".
    

    为什么? 我不能按此顺序删除,因为约束在事务结束前不应生效?

    1 回复  |  直到 15 年前
        1
  •  10
  •   Dan LaRocque    15 年前

    使用 ON DELETE NO ACTION DEFERRABLE ON DELETE RESTRICT DEFERRABLE . 使用 RESTRICT NO ACTION DEFERRABLE 修饰语。

    manual page for CREATE TABLE :

    限制

    紧跟在这句话后面的是 不采取行动 :

    不采取行动

    限制

    生成一个错误,指示删除或更新将创建外键约束冲突。这与无操作相同,只是检查不可延迟。

    如你所见, 不采取行动 限制 ,除了 不采取行动 可延期。这就是我推荐它的原因——我想这正是你想要的。