Внешний ключ на праймари ключ таблицы самой на себя

Рейтинг: 0Ответов: 1Опубликовано: 12.05.2023

CREATE TABLE Tasks(
    "Title" VARCHAR PRIMARY KEY,
    "ParentTask" VARCHAR DEFAULT NULL,
    CONSTRAINT fk_tasks_parent_task FOREIGN KEY ("ParentTask") REFERENCES Tasks("Title")
);

Есть вот такая таблица. Есть ли возможность во второй столбец вставлять одинаковые значения из 1го?

Task ParentTask
First null
Second First
Third Second
Forth Second

Нужно вставить в неё вот такие данные. Но из-за попытки 2 раза во 2й столбец вставить "Second" вылетает ошибка 'Key is not present in table'

Ответы

▲ 2

Либо вставлять данные строго в порядке корректности связей:

insert into tasks values ('First', null);
insert into tasks values ('Second', 'First');
insert into tasks values ('Third','Second'), ('Forth','Second');

либо изменить constraint на DEFERRABLE

CREATE TABLE Tasks(
    "Title" VARCHAR PRIMARY KEY,
    "ParentTask" VARCHAR DEFAULT NULL,
    CONSTRAINT fk_tasks_parent_task FOREIGN KEY ("ParentTask") REFERENCES Tasks("Title") DEFERRABLE INITIALLY IMMEDIATE
);
begin;
set constraints fk_tasks_parent_task DEFERRED;
insert into tasks values ('First', null), ('Second', 'First'), ('Third','Second'), ('Forth','Second');
commit;

Если ограничение объявить как DEFERRABLE INITIALLY DEFERRED - то отдельная команда set constraints будет не нужна и проверка будет по-умолчанию откладываться на время commit.

Неудобный момент в том, что при отложенной проверке ограничений будет дольше выполнятся сам commit, а не непосредственно модифицирующие данные запросы. Если, например, заметили в логах, что commit выполнялся 200мс - то будет мало понятно, почему и какие ограничения он перепроверял.