SQL Server - поддержание ссылочной целостности без триггеров CASCADE и INSTEAD OF

У меня есть таблица (TableB), у которой есть отношения внешнего ключа с родительской таблицей (TableA).

Когда я удаляю запись в таблице A, я хочу сохранить ссылочную целостность, удаляя все записи в TableB, которые ссылаются на удаленную запись в TableA.

Обычно я бы УДАЛЯЛ КАСКАД. Однако из-за структуры таблицы и чрезмерных защитных мер против нескольких каскадных путей в SQL Server это невозможно для данной конкретной связи.

Я также не могу использовать триггер INSTEAD OF, поскольку у самого TableA есть отношения внешнего ключа CASCADE.

Я собираюсь изменить отношения между TableA и TableB на ON DELETE SET NULL, а затем создать триггер AFTER для очистки записей NULL в TableB.

Есть ли лучшие способы справиться с этим сценарием?


person Brett Postin    schedule 27.01.2012    source источник
comment
Можете ли вы объяснить, что вы имеете в виду, из-за структуры таблицы и чрезмерных защитных мер против нескольких каскадных путей и, возможно, включить ваши определения таблиц?   -  person JohnFx    schedule 27.01.2012
comment
Я понимаю, что в первую очередь люди думают о том, чтобы взглянуть на дизайн, однако я не думаю, что это особенно необоснованно, и в любом случае реструктуризация не является вариантом. Так что я просто ищу предложения о том, как решить эту конкретную проблему без изменения дизайна. Я думаю, что этот ответ суммирует мою ситуацию и мысли о том, что SQL Server защищает каскадное удаление, вызывающее несколько каскадных путей   -  person Brett Postin    schedule 27.01.2012
comment
Просто любопытно, какие реальные ограничения мешают вам выполнить удаление дочерней таблицы с последующим удалением родительской таблицы, при этом оба, возможно, заключены в транзакцию?   -  person Philip Kelley    schedule 27.01.2012
comment
Похоже, вы уже на несколько уровней усложняете эту каскадную проблему. Я действительно предлагаю переработать ваши таблицы, чтобы воспользоваться встроенными функциями SQL. Я просто не думаю, что вы собираетесь придумать лучший ответ, чем тот, который встроен в платформу.   -  person JohnFx    schedule 27.01.2012
comment
@PhilipKelley Для этого нет реальных ограничений, и я уже рассматривал это как альтернативное решение. Однако, если я могу позволить базе данных применять RI в тех случаях, когда кто-то может напрямую изменять данные (маловероятно, но возможно), это было бы предпочтительнее.   -  person Brett Postin    schedule 27.01.2012
comment
Я не понимаю автоматически, почему тот факт, что сама TableA имеет отношение внешнего ключа CASCADE, мешает вам использовать триггер AFTER. Я уверен, что ударил бы себя по лбу, когда разберусь. Могли бы вы объяснить?   -  person ErikE    schedule 06.02.2012
comment
@ErikE Связь между TableB и TableA имеет ссылочную целостность. Поэтому, когда запись из TableA удаляется, записи в TableB, которые ссылаются на эту удаленную запись, нарушают целостность до того, как может быть вызван триггер AFTER.   -  person Brett Postin    schedule 06.02.2012
comment
@Poz Как я уже сказал, я знал, что ударю себя ... да, конечно, удаление не должно происходить после триггера, иначе это происходит не в нужный момент в процессе ...   -  person ErikE    schedule 06.02.2012
comment
Это все еще работает? Используя SQL Server 2016, я обнаружил, что он предотвращает on delete set null в тех же обстоятельствах, что и on delete cascade.   -  person Neutrino    schedule 20.02.2020
comment
Только что понял, моя ситуация немного отличается в том, что у меня есть 3 связанные таблицы, TableB ссылается на TabeA, TableC ссылается на TableA, а TableC ссылается на TableB. Таблицы B и C каскадно удаляются из TableA, но мне также нужно, чтобы TableC удалялся, когда TableB удаляется из. Кажется, SQL Server - единственная база данных, которая не может справиться с этим.   -  person Neutrino    schedule 21.02.2020


Ответы (1)


Можете ли вы изменить другое ограничение, которое мешает вам добавить это ограничение как ON DELETE CASCADE?

Можете ли вы добавить столбец DeleteMe, затем выдать UPDATE A SET DeleteMe = 1, а затем использовать триггер after для удаления сначала строк таблицы B, а затем запрошенных строк таблицы A?

Можете ли вы разделить или объединить таблицы (то есть по вертикали) каким-либо образом, чтобы разделить их взаимоисключающие зависимости?

person ErikE    schedule 06.02.2012
comment
1. Я мог бы нарушить каскадный путь в другом месте. Однако эти отношения были бы для меня идеальным местом, поскольку они наименее важны. 2. Это сработает, но я бы предпочел аналогичное решение SET NULL. 3. Я не думаю, что это устранит множественные каскадные пути. - person Brett Postin; 06.02.2012
comment
Пункт 3. зависит от того, как вы разделяете таблицы, и от конкретной природы ваших множественных ограничений для одного и того же столбца. Итак, учитывая то, что вы сказали, похоже, что ваша идея об обновлении до NULL сработает. +1 за хороший вопрос. - person ErikE; 06.02.2012