微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL的“Deferrable Delete”仍然符合Delete的限制

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

我希望在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".

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

解决方法

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

这是manual page for CREATE TABLE的细则:

referential actions other than the NO ACTION check cannot be deferred,even if the constraint is declared deferrable.

显然,上述警告包括RESTRICT.

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

NO ACTION

Produce an error indicating that the deletion or update would create a foreign key constraint violation. If the constraint is deferred,this error will be produced at constraint check time if there still exist any referencing rows. This is the default action.

RESTRICT

Produce an error indicating that the deletion or update would create a foreign key constraint violation. This is the same as NO ACTION except that the check is not deferrable.

如您所见,NO ACTION的行为与RESTRICT完全相同,只是NO ACTION可以推迟.这就是我推荐它的原因 – 我认为这正是你所要求的.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐