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

时间:2015-03-27 16:32:55

标签: sql postgresql foreign-keys referential-integrity

我有两个表,object和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引用回对象的列不是一个选项。

3 个答案:

答案 0 :(得分:6)

对于你的FK约束的ON UPDATE SET NULL修饰符来说,这是一个完美的工作。 Per documentation:

  

SET NULL

     

将引用列设置为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。

除此之外,这听起来很奇怪:

  

我有两个表,object和object_data,带有对象引用   object_data by foreign key(关系是1:1)

通常情况下,在这种情况下,我希望引用是object_data object的另一种方式,但这只是猜测来自表名。

答案 1 :(得分:4)

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

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

答案 2 :(得分:0)

您可以创建临时表:

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

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

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);