Какое поведение по умолчанию при удалении записи, на которую ссылается внешний ключ в PostgreSQL?

Ответ

В PostgreSQL, если при создании внешнего ключа не указано действие ON DELETE явно, по умолчанию применяется NO ACTION. Это предотвращает удаление записи в родительской таблице, если на неё существуют ссылки в дочерней.

Пример с поведением по умолчанию:

CREATE TABLE authors (
    id SERIAL PRIMARY KEY,
    name TEXT
);

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    author_id INTEGER REFERENCES authors(id) -- Подразумевается ON DELETE NO ACTION
);
-- DELETE FROM authors WHERE id = 1; -- Вызовет ошибку, если у автора есть книги.

Важное отличие от RESTRICT: В PostgreSQL NO ACTION и RESTRICT схожи, но NO ACTION проверяет ограничение в конце операции (отложенная проверка, если транзакция не завершена), а RESTRICT — немедленно. На практике при DELETE без отложенных ограничений разницы нет.

Ответ 18+ 🔞

Слушай, а вот это вообще пиздец как интересно, я тебе скажу! Сидишь ты такой, пишешь свои таблички, связываешь авторов с книжками, и думаешь: "Ну, вроде всё логично, хуле тут". А потом бац — и пытаешься удалить какого-нибудь Толстого, а он тебе: "Не-не-не, браток, постой, у меня же 'Война и мир' на полке висит, ёпта!"

Так вот, в этой вашей PostgreSQL, если ты, такой хитрожопый, не указал явно, что делать при удалении (ON DELETE), то система по умолчанию подсовывает тебе NO ACTION. А это значит: "Мужик, ты че, охуел? Не трогай папу, пока от него детишки не отвязались!" Удаление просто сломается об ошибку, если хоть одна ссылочка осталась.

Смотри, как это выглядит в коде, тут всё честно:

CREATE TABLE authors (
    id SERIAL PRIMARY KEY,
    name TEXT
);

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    author_id INTEGER REFERENCES authors(id) -- Тут тихо подразумевается ON DELETE NO ACTION, блядь
);
-- DELETE FROM authors WHERE id = 1; -- Эта команда вызовет такую ошибку, что мало не покажется, если у автора есть хоть одна книжка.

А теперь, внимание, самый сок, ёбаный в рот! Есть ещё RESTRICT, который вроде как делает то же самое — не даёт удалять. Но разница-то, сука, в тонкостях! NO ACTION может немного подождать и проверить ограничение в самом конце операции (особенно если транзакция ещё не завершена, а ограничения отложенные). А RESTRICT — это такой принципиальный уёбок, который сразу орёт: "Стоять! Не двигаться! Я щас проверю!" и блокирует всё нахуй немедленно.

Хотя, если честно, в большинстве повседневных сценариев, когда ты не ебёшь мозг с отложенными проверками, разницы — хуй с горы. Оба варианта просто не пустят тебя в родительскую таблицу с топором.