Когда / зачем использовать каскадирование в SQL Server?



при настройке внешних ключей в SQL Server, при каких обстоятельствах вы должны иметь его каскад на удаление или обновление, и каковы причины этого?



Это, вероятно, относится и к другим базам данных.



Я ищу больше всего конкретных примеров каждого сценария, предпочтительно от кого-то, кто их успешно использовал.

1658   15  

15 ответов:

резюме того, что я видел до сих пор:

  • некоторые люди вообще не любят каскадировать.

Каскадное Удаление

  • каскадное удаление может иметь смысл, когда семантика отношения может включать эксклюзив "часть" описание. Например, запись строки заказа является частью родительского заказа, и строки заказа никогда не будут совместно использоваться несколькими заказами. Если приказ должен был исчезнуть, линия заказа должна была как ну, и линия без заказа была бы проблемой.
  • каноническим примером для каскадного удаления является SomeObject и SomeObjectItems, где нет никакого смысла для записи элементов когда-либо существовать без соответствующей основной записи.
  • вы должны не используйте Cascade Delete, если вы сохраняете историю или используете "мягкое / логическое удаление", где вы только устанавливаете столбец удаленных битов в 1/true.

Каскад Обновление

  • каскадное обновление может иметь смысл, когда вы используете реальный ключ, а не суррогатный ключ (столбец identity/autoincrement) в таблицах.
  • канонический пример для каскадного обновления - это когда у вас есть изменяемый внешний ключ, например имя пользователя, которое можно изменить.
  • вы должны не используйте каскадное обновление с ключами, которые являются столбцами идентификации/автоинкремента.
  • каскадное обновление лучше всего использовать в сочетании с уникальным ограничение.

Когда Использовать Каскадирование

  • вы можете получить дополнительное сильное подтверждение от пользователя, прежде чем разрешить каскадную операцию, но это зависит от вашего приложения.
  • каскадирование может привести к неприятностям, если вы неправильно настроите свои внешние ключи. Но с тобой все будет в порядке, если ты все сделаешь правильно.
  • неразумно использовать каскадирование, прежде чем вы его полностью поймете. Тем не менее, это полезная функция, и поэтому стоит потратить время, чтобы понять.

внешние ключи-это лучший способ обеспечить ссылочную целостность базы данных. Избегать каскадов из-за магии-это как писать все в сборке, потому что вы не доверяете магии за компиляторами.

что плохо, так это неправильное использование внешних ключей, например, создание их в обратном направлении.

пример Хуана Мануэля является каноническим примером, если вы используете код, есть гораздо больше шансов оставить ложные DocumentItems в базе данных, которые придут и укусить вас.

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

@Эйдан, эта ясность, на которую вы ссылаетесь, имеет высокую стоимость, вероятность оставить ложные данные в вашей базе данных, которая не маленький. Для меня это обычно просто отсутствие знакомство с БД и невозможность найти, какие ФК находятся на месте, прежде чем работать с БД, которые способствуют этому страху. Либо это, либо постоянное злоупотребление каскадом, используя его там, где сущности не были концептуально связаны, или где вы должны сохранить историю.

Я никогда не использую каскадные удаления.

Если я хочу что-то удалить из базы данных, я хочу явно сказать базе данных, что я хочу вынуть.

конечно, они являются функцией, доступной в базе данных, и могут быть случаи, когда их можно использовать, например, если у вас есть таблица "order" и таблица "orderItem", вы можете очистить элементы при удалении заказа.

Мне нравится ясность, которую я получаю от выполнения этого в коде (или сохраненном процедура), а не "волшебство" происходит.

по той же причине я тоже не поклонник триггеров.

следует отметить, что если вы удалите "заказ", вы получите отчет "1 Row affected", даже если каскадное удаление удалило 50 'orderItem.

Я много работаю с каскадными удалениями.

приятно знать, что тот, кто работает против базы данных, никогда не оставит никаких нежелательных данных. Если зависимости растут, я просто изменяю ограничения в диаграмме в Management Studio, и мне не нужно настраивать sp или dataacces.

тем не менее, у меня есть 1 проблема с каскадными удалениями и это циклические ссылки. Это часто приводит к частям базы данных, которые не имеют каскадных удалений.

один пример, когда у вас есть зависимости между сущностями... ie: Document - > DocumentItems (когда вы удаляете документ, DocumentItems не имеют причины для существования)

Я делаю много работы с базой данных и редко нахожу каскадные удаления полезными. Единственный раз, когда я использовал их эффективно, находится в базе данных отчетов, которая обновляется ночной работой. Я удостоверяюсь, что любые измененные данные импортируются правильно, удаляя любые записи верхнего уровня, которые изменились с момента последнего импорта, а затем повторно импортируйте измененные записи и все, что связано с ними. Это избавит меня от необходимости писать много сложных удалений, которые выглядят снизу вверх в моей базе данных.

Я не считаю каскадные удаления такими же плохими, как триггеры, поскольку они удаляют только данные, триггеры могут иметь все виды неприятных вещей внутри.

в целом я избегаю реальных удалений вообще и использую логические удаления (т. е. имея битовый столбец с именем isDeleted, который получает значение true) вместо этого.

использовать каскадное удаление, где вы хотели бы записывать с ФК должен быть удален, если его ссылаясь ПК запись была удалена. Другими словами, где запись бессмысленна без ссылки на запись.

Я считаю cascade delete полезным, чтобы гарантировать, что мертвые ссылки удаляются по умолчанию, а не вызывают исключения null.

при удалении каскада:

Если вы хотите строки в дочерней таблице для удаления если соответствующая строка удаляется в родительской таблице.

Если при каскадном удалении не используется, то ошибка будет поднят на целостность.

на каскаде обновления:

Если вы хотите изменение первичного ключа для обновления в внешний ключ

одна из причин, чтобы положить в каскадном удалении (а не делать это в коде), чтобы улучшить производительность.

Случай 1: с каскадным удалением

 DELETE FROM table WHERE SomeDate < 7 years ago;

случай 2: Без каскадного удаления

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

во-вторых, когда вы добавляете дополнительную дочернюю таблицу с каскадным удалением, код в случае 1 продолжает работать.

Я бы только поставил Каскад, где семантика отношения является "частью". Иначе какой-нибудь идиот удалит половину вашего база данных, когда вы делаете:

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

Я стараюсь избегать удаления или обновления, которые я явно не запрашивал в SQL server.

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

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

Я, как и все здесь, считаю, что каскадные удаления действительно только незначительно полезны (это действительно не так много работы для удаления ссылочных данных в других таблицах-если есть много таблиц, вы просто автоматизируете это с помощью скрипта), но очень раздражает, когда кто-то случайно каскад удаляет некоторые важные данные, которые трудно восстановить.

единственный случай, когда я бы использовал, если данные в таблице-это хорошо контролируемое (например, ограниченные разрешения) и только обновлено или удалено с помощью контролируемого процесса (например, обновления программного обеспечения), который был проверен.

Я слышал о DBAs и / или" политике компании", которые запрещают использовать" on Delete Cascade " (и другие) исключительно из-за плохого опыта в прошлом. В одном случае парень написал три триггера, которые в конечном итоге позвонили друг другу. Три дня на восстановление привели к полному запрету на триггеры, все из-за действий одного идиота.

конечно, иногда триггеры необходимы вместо "on Delete cascade", например, когда некоторые дочерние данные должны быть сохранены. Но в других случаях ее вполне допустимо использовать метод on Delete cascade. Ключевое преимущество "on Delete cascade" заключается в том, что он захватывает все дочерние элементы; пользовательская записанная процедура триггера/хранилища может не быть, если она не закодирована правильно.

Я считаю, что разработчику должно быть разрешено принимать решение, основанное на том, что такое разработка и что говорит спецификация. Запрет ковра, основанный на плохом опыте, не должен быть критерием; процесс мышления "никогда не использовать" в лучшем случае драконовский. Приговор должен быть вносятся каждый раз, и изменения вносятся по мере изменения бизнес-модели.

разве это не то, что развития вообще?

удаление или обновление до S, которое удаляет значение внешнего ключа, найденное в некоторых кортежах R, может быть обработано одним из трех способов:

  1. отказ
  2. распространение
  3. недействительным.

распространение называется каскадным.

есть два случая:

‣ Если Кортеж в S был удален, удалите кортежи R, которые ссылались на него.

‣ Если Кортеж в S был обновлен, обновите значение в R кортежи, которые ссылаются на него.

Если вы работаете в системе с множеством различных модулей в разных версиях, это может быть очень полезно, если удаленные элементы каскада являются частью / принадлежат держателю PK. В противном случае все модули потребуют немедленных исправлений для очистки своих зависимых элементов перед удалением владельца PK, или отношение внешнего ключа будет полностью опущено, возможно, оставив тонны мусора в системе, если очистка не выполняется правильно.

Я только что ввел каскадное удаление для нового таблица пересечений между двумя уже существующими таблицами (пересечение для удаления только), после каскадного удаления было отброшено в течение довольно долгого времени. Это также не так уж плохо, если данные теряются.

Это, однако, плохая вещь в таблицах перечислений: кто-то удаляет запись 13 - yellow из таблицы "цвета", и все желтые элементы в базе данных удаляются. Кроме того, они иногда обновляются способом "удалить все вставки", что приводит к полному отсутствию ссылочной целостности. Из конечно, это неправильно, но как вы измените сложное программное обеспечение, которое работает уже много лет, с введением настоящих ссылочной целостности риска неожиданных побочных эффектов?

другая проблема заключается в том, что исходные значения внешнего ключа должны сохраняться даже после удаления первичного ключа. Можно создать столбец tombstone и параметр on DELETE SET NULL для исходного FK, но для этого снова требуются триггеры или конкретный код для поддержания избыточности (за исключением после PK deletion) значение ключа.

каскадные удаления чрезвычайно полезны при реализации логических сущностей супертипа и подтипа в физической базе данных.

когда отдельные таблицы супертипов и подтипов используются для физической реализации супертипов/подтипов (в отличие от свертывания всех атрибутов подтипов в одну физическую таблицу супертипов), между этими таблицами существует взаимно однозначная связь, и тогда проблема заключается в том, как сохранить первичные ключи 100% в синхронизации между этими таблицами таблицы.

каскадные удаления могут быть очень полезным инструментом для:

1) Убедитесь, что удаление записи супертипа также удаляет соответствующую запись одного подтипа.

2) Убедитесь, что любое удаление записи подтипа также удаляет запись супертипа. Это достигается путем реализации триггера удаления" вместо " в таблице подтипов, который идет и удаляет соответствующую запись супертипа, которая, в свою очередь, каскадно удаляет подтип запись.

использование каскадных удалений таким образом гарантирует, что никакие бесхозные записи супертипа или подтипа никогда не существуют, независимо от того, удаляете ли вы сначала запись супертипа или запись подтипа.

Comments

    Ничего не найдено.