加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-13 16:01:56 所属栏目:百科 来源:网络整理
导读:我想删除两个表中的行,这两个表通过一组可延迟的约束相互依赖.为了简化这篇文章,我模拟了一个简单的数据库模式. 我希望在SQL事务/数据库补丁中删除某些表中的条目’delete_from_me’.问题是,我想在松开链接本身之前根据第二个表’constraining_table’中的选
我想删除两个表中的行,这两个表通过一组可延迟的约束相互依赖.为了简化这篇文章,我模拟了一个简单的数据库模式.

我希望在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可以推迟.这就是我推荐它的原因 – 我认为这正是你所要求的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读