Хорошее объяснение поведения каскада (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 или что-то подобное, чтобы устранить двусмысленность. У кого-нибудь есть какие-то мнемоники для запоминания этого?

76 голосов | спросил John Syrinek 20 J0000006Europe/Moscow 2013, 18:18:32

4 ответа


116

Если вам нравятся термины Родитель и Ребенок , и вы чувствуете, что их легко запомнить, вы может понравиться перевод ON DELETE CASCADE на Leave No Orphans!

Это означает, что когда строка Parent удаляется (убивается), ни одна из сиротских строк не должна оставаться в живых в таблице Child. Все дети родительской строки также убиты (удалены). Если у любого из этих детей есть внуки (в другой таблице через другой внешний ключ), и существует ON DELETE CASCADE, они также должны быть убиты (и все потомки, если есть каскадный эффект определены.)

Ограничение FOREIGN KEY также может быть описано как Allow No Orphans! (в первую очередь). Нет Ребенок должен когда-либо разрешаться (записываться) в дочерней таблице, если он не имеет Parent (строка в родительской таблице).

Для согласованности ON DELETE RESTRICT можно перевести на (менее агрессивно) Вы не можете убивать родителей! Только бездетные строки может быть убит (удален.)

ответил ypercubeᵀᴹ 20 J0000006Europe/Moscow 2013, 19:00:40
28
  

Например, если у меня есть две таблицы - Родительский и Ребенок - где Ребенок   записи принадлежат родительским записям, для таблицы которых необходимо ВКЛЮЧИТЬ УДАЛЕНИЕ   CASCADE?

ON DELETE CASCADE является необязательным предложением в объявлении внешнего ключа. Таким образом, с объявляет внешний ключ. (Значение в таблице «child».)

  

... это может означать удаление записи родителя, когда запись Child   удалено, или это может означать удаление записи Child, когда родитель   удален. Итак, что это?

Один из способов интерпретации объявления внешнего ключа: «Все допустимые значения для этого столбца относятся к« this_column »в« this_table ».» Когда вы удаляете строку в «дочерней» таблице, никто не заботится. Это не влияет на целостность данных.

Когда вы удаляете строку из «родительской» таблицы - из «that_table» - вы удаляете допустимое значение из возможных значений для «дочерней» таблицы. Чтобы сохранить целостность данных, вы должны сделать что-то в «дочернюю» таблицу. Каскадные удаления - это одно, что вы можете сделать.

ответил Mike Sherrill 'Cat Recall' 20 J0000006Europe/Moscow 2013, 18:35:46
0

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 = 'Путин';
      КОНЕЦ;
      

      В такой системе ограничение проверяется только до совершения транзакции. Это может привести к остановке революции, но вы можете восстановить транзакцию - в некоторой степени «восстановить».

ответил Evan Carroll 26 J000000Thursday18 2018, 00:42:15
-3

ну, возможно, мы можем рационализировать синтаксис. Возьмем пример 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 записей из базы данных, которые обычно будут выполняться администратором пользовательского интерфейса, часто избегая причастности к стороне администратора базы данных.]

ответил George Mogilevsky 20 J000000Friday18 2018, 08:59:25

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132