如果删除带有外键的行,如何在表中留一行外键值?

问题描述 投票:1回答:2

有表1:

CREATE TABLE table1
(
  id serial NOT NULL,
  CONSTRAINT pk_table1_id PRIMARY KEY (id),
)

有表2:

CREATE TABLE table2
(
  id serial NOT NULL,
  fk_1 integer,
  CONSTRAINT fk_to_table1 FOREIGN KEY (fk_1)
      REFERENCES table1 (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE NO ACTION
      NOT VALID
)

当我尝试从table1删除一些行时,我得到了异常:

UPDATE or DELETE in the table "table1" violates the foreign key constraint "fk_to_table1" of the table "table2"

如果删除了来自table1的外键的行,是否有某种方法可以在table2中保留(保存)具有相同值的行(fk_1(来自table1的id)?

示例:表1:

id
1
2
3

Teble2:

id fk_1
1 | 1
2 | 1
3 | 3
4 | 2

从table1删除第一行后我想看到的内容:

表格1:

id
2
3

Teble2:

id fk_1
1 | 1
2 | 1
3 | 3
4 | 2
postgresql
2个回答
0
投票

你可以使用ON DELETE SET NULL做到这一点:

CREATE TABLE table2
(
  id int NOT NULL,
  fk_1 integer,
  CONSTRAINT fk_to_table1 FOREIGN KEY (fk_1)
      REFERENCES table1 (id)
      ON UPDATE CASCADE 
      ON DELETE SET NULL
);

insert into table1 values (1), (2);
insert into table2 values (1,1), (2,1), (3,2), (4,2);

然后,如果你运行:

delete from table1
where id = 1;

表2将如下所示:

id | fk_1
---+-----
 1 |     
 2 |     
 3 |    2
 4 |    2

在线示例:http://rextester.com/NPUG18060


0
投票

简短的回答是:你做不到。

外键的目的是验证只要该属性具有值,该值就在引用的表中(除非值为NULL ---表中不需要NULL)。

两个建议:

解决方案1.将元组保留在表2中,不要删除它。相反,添加一个布尔属性,确定是否已删除元组。

专门针对您的问题。添加删除到表的属性。将if设置为false。当删除元组时,创建一个触发器,将此属性设置为true。这很麻烦且容易出错。

解决方案2(这是我的首选解决方案)。您可以使用通过触发器管理的第三个表。每次添加table2中的元组时,都会添加一个表3的元组。表3只有一个属性(您希望引用外键的属性)。 Table3将是属于Table2的属性的所有值的集合。添加到Table3的触发器应该使用upsert,以防之前已经看到添加的属性。然后,Table1将具有指向Table3的外键约束。

© www.soinside.com 2019 - 2024. All rights reserved.