8

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

我希望从 SQL 事务/数据库补丁中的某个表“delete_from_me”中删除条目。问题是,我想在松开链接本身之前根据第二个表“constraining_table”中的选择进行删除。

下面是对这两个表的描述:

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".

这似乎是一个很好的临时表候选者,但是我想知道为什么我不能按这个顺序删除,因为约束在事务结束之前不应该有效?

4

1 回答 1

12

使用ON DELETE NO ACTION DEFERRABLE而不是ON DELETE RESTRICT DEFERRABLE. 使用RESTRICT而不是NO ACTION强制约束不可延迟,无论您是否应用DEFERRABLE修改器。

这是手册页CREATE TABLE的细则:

不能延迟除 NO ACTION 检查以外的引用操作,即使约束被声明为可延迟也是如此。

显然,上述警告包括RESTRICT.

在这句话之后不久是NO ACTION和的定义RESTRICT

无动作

产生一个错误,指示删除或更新将创建外键约束违规。如果约束被延迟,如果仍然存在任何引用行,则会在约束检查时产生此错误。这是默认操作。

严格

产生一个错误,指示删除或更新将创建外键约束违规。这与 NO ACTION 相同,只是支票不可延期。

如您所见,除了可延期外,其NO ACTION行为与 相同。这就是我推荐它的原因——我认为这正是你所要求的。RESTRICTNO ACTION

于 2010-07-19T16:48:17.237 回答