Как оставить строку в таблице со значением внешнего ключа, если строка с внешним ключом удалена? - PullRequest
0 голосов
/ 25 апреля 2018

Есть таблица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
)

Когда я пытаюсь удалить строку из таблицы1, я получаю исключение:

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

Есть ли способ оставить (сохранить) строку в таблице 2 с таким же значением в fk_1 (идентификатор из таблицы 1), если строка с внешним ключом из таблицы 1 удалена?

Пример: Таблица1:

id
1
2
3

Teble2:

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

Что я хочу увидеть после удаления первой строки из таблицы1:

Table1:

id
2
3

Teble2:

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

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Краткий ответ: вы не можете.

цель внешнего ключа состоит в том, чтобы убедиться, что всякий раз, когда этот атрибут имеет значение, значение находится в ссылочной таблице (кроме случаев, когда значение равно NULL---NULL не обязательно должен существовать в таблице).

Два предложения:

Решение 1. Сохраните кортеж в таблице 2, не удаляйте его.Вместо этого добавьте логический атрибут, который определяет, был ли кортеж удален.

Специально для вашей проблемы.Добавьте атрибут, удаленный в таблицу.Установите для по умолчанию значение false.И когда кортеж будет удален, создайте триггер, чтобы вместо этого атрибута установить значение true.Это громоздко и подвержено ошибкам.

Решение 2 (это мое предпочтительное решение).Вы можете использовать третью таблицу, которая управляется с помощью триггеров.Каждый раз, когда добавляется кортеж в table2, добавляется кортеж в table3.Table3 будет иметь только один атрибут (тот, на который вы хотите ссылаться на внешний ключ).Table3 будет набором всех значений атрибута, которые были частью Table2.Триггер для добавления в Table3 должен использовать upsert, если добавленный атрибут уже был виден ранее.В этом случае Table1 будет иметь ограничение внешнего ключа, указывающее на Table3.

0 голосов
/ 25 апреля 2018

Вы можете сделать это, используя 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;

Table2 будет выглядеть следующим образом:

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

Онлайн пример: http://rextester.com/NPUG18060

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...