Хорошее объяснение поведения каскада (ON DELETE /UPDATE)
Я не разрабатываю схемы каждый день, но когда я это делаю, я пытаюсь настроить каскадные обновления /удаления правильно, чтобы упростить администрирование. Я понимаю, как работают каскады, но я никогда не могу вспомнить, какая таблица - это какая.
Например, если у меня есть две таблицы - Parent
и Child
- с внешним ключом в Child
, который ссылается на Parent
и имеет ON DELETE CASCADE
, который записывает триггер каскада и какие записи удаляются каскадом? Мое первое предположение заключалось в том, что записи Child
будут удалены при удалении записей Parent
, так как записи Child
зависят от Parent
записей, но ON DELETE
является неоднозначным; это может означать удаление записи Parent
, когда запись Child
удалена, или это может означать удаление записи Child
, когда Parent
удаляется. Итак, что это?
Я хочу, чтобы синтаксис был ON PARENT DELETE, CASCADE
, ON FOREIGN DELETE, CASCADE
или что-то подобное, чтобы устранить двусмысленность. У кого-нибудь есть какие-то мнемоники для запоминания этого?
4 ответа
Если вам нравятся термины Родитель
и Ребенок
, и вы чувствуете, что их легко запомнить, вы может понравиться перевод ON DELETE CASCADE
на Leave No Orphans!
Это означает, что когда строка Parent
удаляется (убивается), ни одна из сиротских строк не должна оставаться в живых в таблице Child
. Все дети родительской строки также убиты (удалены). Если у любого из этих детей есть внуки (в другой таблице через другой внешний ключ), и существует ON DELETE CASCADE
, они также должны быть убиты (и все потомки, если есть каскадный эффект определены.)
Ограничение FOREIGN KEY
также может быть описано как Allow No Orphans!
(в первую очередь). Нет Ребенок
должен когда-либо разрешаться (записываться) в дочерней таблице, если он не имеет Parent
(строка в родительской таблице).
Для согласованности ON DELETE RESTRICT
можно перевести на (менее агрессивно) Вы не можете убивать родителей!
Только бездетные строки может быть убит (удален.)
Например, если у меня есть две таблицы - Родительский и Ребенок - где Ребенок записи принадлежат родительским записям, для таблицы которых необходимо ВКЛЮЧИТЬ УДАЛЕНИЕ CASCADE?
ON DELETE CASCADE является необязательным предложением в объявлении внешнего ключа. Таким образом, с объявляет внешний ключ. (Значение в таблице «child».)
... это может означать удаление записи родителя, когда запись Child удалено, или это может означать удаление записи Child, когда родитель удален. Итак, что это?
Один из способов интерпретации объявления внешнего ключа: «Все допустимые значения для этого столбца относятся к« this_column »в« this_table ».» Когда вы удаляете строку в «дочерней» таблице, никто не заботится. Это не влияет на целостность данных.
Когда вы удаляете строку из «родительской» таблицы - из «that_table» - вы удаляете допустимое значение из возможных значений для «дочерней» таблицы. Чтобы сохранить целостность данных, вы должны сделать что-то в «дочернюю» таблицу. Каскадные удаления - это одно, что вы можете сделать.
SQL: 2011 Spec
Существует пять опций для ON DELETE
и ON UPDATE
, которые могут применяться к FOREIGN KEY
. Они называются <ссылочные действия>
, непосредственно из спецификации SQL: 2011
ON DELETE CASCADE
: если строка ссылочной таблицы удалена, то все соответствующие строки в таблице ссылок удаляются.ON DELETE SET NULL
: если строка ссылочной таблицы удалена, то все ссылки на столбцы во всех совпадающих строках таблицы ссылок должны быть установлены в нуль.ON DELETE SET DEFAULT
: если строка ссылочной таблицы удалена, то все ссылочные столбцы во всех соответствующих строках таблицы ссылок должны быть установлены на значение по умолчанию для столбца.ON DELETE RESTRICT
: запрещается удалять строку ссылочной таблицы, если эта строка имеет соответствующие строки в таблице ссылок.ВКЛ. УДАЛИТЬ НЕТ ДЕЙСТВИЙ
(по умолчанию) : нет действия ссылочного удаления; референтное ограничение указывает только проверку ограничений.
Внешний ключ устанавливает зависимые отношения. <ссылочное действие>
определяет, что происходит, когда связь растворяется.
Пример /Метафора /Объяснение
В этом примере мы примем общую модель общества и экономики: где каждый бизнес
- это компания, которая поддерживает связь с буржуазией
через fatcat_owner
.
CREATE TABLE буржуазия (
fatcat_owner varchar (100) ПЕРВИЧНЫЙ КЛЮЧ
);
ВСТАВИТЬ В буржуазию (fatcat_owner) ЦЕННОСТИ
(«Братья Коча»);
CREATE TABLE бизнес (
имя varchar (100),
fatcat_owner varchar (100) ССЫЛКИ Буржуазия
);
INSERT INTO бизнес (имя, fatcat_owner)
ЦЕННОСТИ («Грузия-Тихий океан», «Братья Кох»);
Если на все business
es влияет буржуазия
через свой fatcat_owner
), то что вы будете делать после революции рабочих, когда это вы очищаете fatcat_owner
и имеете бесклассовое общество?
- Viva la revolución
НАЧАТЬ;
УДАЛИТЬ ОТ буржуазии;
КОНЕЦ;
У вас есть несколько вариантов,
- Остановите революцию. В языке SQL,
RESTRICT
. Некоторые люди считают, что это меньшее зло, но обычно они ошибаются. -
Позвольте ему продолжить. Если так, когда происходит революция, SQL дает вам четыре варианта,
-
SET NULL
- оставьте поле пустым. Кто знает, может быть, капитализм восстанавливается, появляетсябуржуазия
, и олигархи заполняют списокfatcat_owners
. Важно отметить, что столбец должен бытьNULLABLE
(неNOT NULL
)), или это никогда не произойдет. -
SET DEFAULT
- возможно, у вас былDEFAULT
, который обрабатывал это?DEFAULT
может вызвать функцию. Возможно, ваша схема уже готова к революции. -
CASCADE
- контроль повреждений отсутствует. Еслибуржуазия
идет, также работаетbusiness
. Если бизнес должен иметьfatcat_pig
, то иногда имеет смысл потерять данные, а не иметь бизнес в таблицеbusiness
. -
NO ACTION
- это по существу метод задержки проверки, в MySQL он не отличается отRESTRICT
, но в PostgreSQL вы сможете сделать- Не настоящая революция. - требует, чтобы ограничение было ОТРИЦАТЕЛЬНО НАЧАЛЬНО ОТРАЖЕНА НАЧАТЬ; УСТАНОВИТЬ ВСЕ ОШИБКИ; УДАЛИТЬ ОТ буржуазии; ВСТАВЬТЕ В буржуазию ЦЕННОСТИ («Путин»); UPDATE business SET fatcat_pig = 'Путин'; КОНЕЦ;
В такой системе ограничение проверяется только до совершения транзакции. Это может привести к остановке революции, но вы можете восстановить транзакцию - в некоторой степени «восстановить».
-
ну, возможно, мы можем рационализировать синтаксис. Возьмем пример Python:
class Parent (self):
# определить поля родителя
класс Ребенок (сам):
# определить дочерние поля
parent_pk_is_childs_foreign_key = models.ForeignKey (родительский, on_delete = models.CASCADE)
, что говорит эта строка, является on_delete родителя (что случайно упоминается в заявлении), пожалуйста, каскадируйте удаление на ребенка. Вот почему оператор CASCADE определен на уровне дочернего уровня, он отмечает тех детей, которые необходимо удалить
Например, если у вас был другой класс
класс GrownUpChild (self):
# определить подросшие дочерние поля
parent_pk_is_childs_foreign_key = models.ForeignKey (родительский, on_delete = models.DO_NOTHING)
эта структура ясно покажет, какой из детей нужно удалить (Ребенок) и которые должны остаться (GrownUpChild), хотя и осиротевшие
[Изменить: учитывая контекст обсуждения, особенно в случаях on_delete = models.CASCADE и т. д.], на самом деле часто бывает желательным поведением оставить детей из удаленного родителя из-за причин аудита и отчетности, а также как восстановление случайных удалений. [конечно, программное обеспечение уровня предприятия будет построено вокруг такого поведения и будет отмечать удаленные записи как удаленные = 1 вместо фактического их удаления, а также не будет включать их в какие-либо запросы для внешнего интерфейса, за вычетом некоторых специально разработанных отчетов. Кроме того, у него будет функция очистки удаленных == 1 записей из базы данных, которые обычно будут выполняться администратором пользовательского интерфейса, часто избегая причастности к стороне администратора базы данных.]