При удалении родителя внешний ключ настроен с действием ON DELETE SET DEFAULT. Какое условие должно выполняться для успешного удаления?
Значение по умолчанию дочернего внешнего ключа после удаления родителя должно ссылаться на существующую строку родительской таблицы. Иначе операция удаления будет отклонена из-за нарушения ссылочной целостности; база данных не создаст родительскую строку автоматически.
Ссылочные действия появились как способ описать типичную реакцию зависимых данных на изменение родительской строки непосредственно в схеме. Это уменьшает зависимость целостности от прикладного кода и защищает данные независимо от того, какой клиент выполняет операцию.
SET DEFAULT предназначен для случаев, когда зависимую запись нельзя удалить, но её связь с конкретным родителем после удаления должна быть заменена на заранее определённое нейтральное состояние.
Представим товары, связанные с категориями. Если удалить категорию, товар может остаться в системе с категорией «Без категории», но такая категория должна существовать как обычная родительская строка.
Если значение по умолчанию отсутствует в родительской таблице, несовместимо по типу или нарушает другие ограничения, удаление родителя не должно завершиться частично. Внешний ключ проверяется после подстановки значения по умолчанию, поэтому операция отклоняется целиком.
При удалении родительской строки база данных выполняет логически эквивалентную последовательность: находит дочерние строки, заменяет их внешний ключ значением DEFAULT, затем проверяет ссылочную целостность. Новое значение обязано соответствовать целевому ключу родительской таблицы.
Минимальный пример:
Для успешного удаления категории с идентификатором 5 в таблице category должна существовать строка с идентификатором 0. Обычно её создают как специальную строку «Без категории» и защищают от удаления.
SET DEFAULT отличается от SET NULL: при SET NULL дочерний столбец должен допускать NULL, а при SET DEFAULT его значение по умолчанию обязано быть допустимой ссылкой. В отличие от CASCADE, дочерние строки не удаляются.
Следует учитывать поддержку конкретной СУБД и особенности применения значения DEFAULT к внешнему ключу. Нельзя полагаться только на наличие синтаксиса: нужно проверить фактическое поведение выбранной СУБД, особенно при составных внешних ключах и сложных ограничениях.
В каталоге интернет-магазина удаляемые категории нельзя каскадно удалять вместе с товарами, поскольку история продаж должна сохраниться. Команда рассмотрела три варианта: CASCADE упрощает очистку, но уничтожает важную историю; SET NULL сохраняет товары, однако требует обработки отсутствующей категории во всех запросах; SET DEFAULT переводит товары в категорию «Без категории» и сохраняет обязательность связи.
Выбрали SET DEFAULT, создали неизменяемую специальную категорию с фиксированным идентификатором и запретили её удаление. В результате удаление обычной категории не теряет товары, а отчёты получают явное состояние вместо неразличимого NULL.
Что произойдёт, если строка со значением по умолчанию будет удалена раньше зависимых строк?
Последующее удаление родителя с SET DEFAULT завершится ошибкой, если подстановка значения по умолчанию создаст ссылку на несуществующую строку. Поэтому специальную родительскую строку нужно защищать от удаления или удалять её только после изменения всех зависимых записей.
Может ли значение по умолчанию быть NULL?
Да, с точки зрения механизма это возможно, если внешний ключ допускает NULL. Но тогда поведение фактически становится близким к SET NULL, а сама связь перестаёт быть обязательной. Если дочерний столбец объявлен NOT NULL, такое значение приведёт к отказу операции удаления.
Создаёт ли SET DEFAULT родительскую строку, если её ещё нет?
Нет. Действие меняет значение внешнего ключа в дочерних строках, но не вставляет данные в родительскую таблицу. Поэтому строка для значения по умолчанию должна быть создана заранее, а её ключ и тип должны быть совместимы с внешним ключом.