PostgreSQL:删除从另一个 table 引用的行

PostgreSQL: deleting rows referenced from another table

我有两个表,对象和 object_data,对象通过外键引用 object_data(关系是 1:1)。对于一组对象,我需要清空它们的 object_data 引用并删除相应的 object_data 行,如下所示:

DELETE FROM object_data WHERE id IN
( SELECT object_data_id FROM object WHERE ... );

UPDATE object SET object_data_id = NULL WHERE ...;

问题是,外键约束不允许删除仍然从对象引用的 object_data 行。

我当前的解决方案是将 SELECT 的结果读入列表,然后清空外键,然后使用 IN 运算符以合理大小的批次删除 object_data 行。有更好的解决方案吗?添加从 object_data 返回到对象的列不是一个选项。

是使用 CTE(通用 Table 表达式)

WITH tmp AS (SELECT object_data_id FROM object WHERE ...),
    upd AS (UPDATE object SET object_data_id = NULL WHERE ...)
DELETE FROM object_data 
  WHERE id IN (SELECT object_data_id FROM tmp);

第一个叫tmp的CTE先执行,然后记住你需要的数据 名为 upd 的第二个 CTE 确实将字段设置为 NULL 最后 DELETE 使用来自 tmp 的数据执行 DELETE

Sons 喜欢 ON UPDATE SET NULL 修饰符对您的 FK 约束的完美工作。 Per documentation:

SET NULL

Set the referencing column(s) to null.

ALTER TABLE object DROP CONSTRAINT <fk_name_here>;

ALTER TABLE object ADD CONSTRAINT <fk_name_here>
FOREIGN KEY ON (object_data_id) REFERENCES object_data (object_data_id)
ON DELETE SET NULL;

猜PK名字也是object_data_id。那么您只需要:

DELETE FROM object_data WHERE id ...

object 中的崇敬自动设置为 NULL。

另外,这听起来很奇怪:

I have two tables, object and object_data, with object referencing object_data by foreign key (the relation is 1:1)

通常,在这种情况下,我希望引用是从 object_data object 的相反方向,但这只是猜测table 个名字。

您可以创建一个临时文件 table:

CREATE TEMP TABLE object_data_ids AS
SELECT object_data_id FROM object WHERE ...;

然后在更新和删除中使用临时 table:

UPDATE object SET object_data_id = NULL WHERE object_data_id IN
(SELECT object_data_id FROM object_data_ids);


DELETE FROM object_data WHERE id IN
(SELECT object_data_id FROM object_data_ids);