Нужно изменить структуру SQL для удаления - PullRequest
1 голос
/ 09 февраля 2010

Хорошо. Я попробовал спусковой крючок, но он не сработал.

У меня есть каскады от A до линкера и от B до линкера, каскад от пользователей до A, без действий от пользователей до B.

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

установить ANSI_NULLS ON установить QUOTED_IDENTIFIER ON идти ALTER TRIGGER [trig_delUser] ON [dbo]. [Aspnet_Users] ДЛЯ УДАЛЕНИЯ КАК УСТАНАВЛИВАЙТЕ NOCOUNT ON; УДАЛИТЬ ИЗ B, ГДЕ B.UserId = Deleted.UserId

Я получаю исключение: оператор DELETE конфликтует с ограничением REFERENCE "FK_B_aspnet_Users"

Я работаю с измененным aspnetdb База данных SQL:

[Частичная схема БД] [2]

У меня есть каскадное удаление на Отношения B_Linker и A_Linker отношения и там, кажется, не быть любая опасность возникновения циклов.

Когда я удаляю пользователя, мне бы хотелось, чтобы все A записи и B записи должны быть удалены вместе с любым связанным компоновщиком записи; к сожалению, SQL mgmt студия только позволит мне поставить каскад удалить правило на ЛИБО aspnet_Users_A или aspnet_Users_B, а не оба.

Что мне нужно сделать?

Большое спасибо.

[2]: http://i48.tinypic.com/2nsnc3k.png

Ответы [ 3 ]

0 голосов
/ 09 февраля 2010

Это одно из печальных и откровенно раздражающих ограничений SQL Server.

Проблема не в том, что могут быть циклы, а в том, что, как говорит ошибка, у вас есть несколько каскадных путей к таблице Linker. Первый - aspnet_Users -> A -> Linker, а второй - aspnet_Users -> B -> Linker.

У вас есть только пара вариантов:

  • Выберите один путь для реализации CASCADE и установите для другого значение NO ACTION. Затем напишите хранимую процедуру, которая удаляет некаскадные дочерние объекты перед удалением родительских объектов, чтобы предотвратить ошибку внешнего ключа. Или не CASCADE, и пусть ваш SP делает каскад для обоих.

  • Во втором отношении вообще не добавляйте внешний ключ; вместо этого используйте триггер FOR DELETE на родительском объекте, чтобы удалить дочерние объекты. Мне очень не нравится использовать триггеры для RI, но это не намного хуже, чем первый вариант. В некотором смысле это лучше, потому что клиенты баз данных не должны беспокоиться о вашей конкретной реализации отношений FK.

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

0 голосов
/ 09 февраля 2010

Я бы не реализовал это через каскад удаления. Или через триггер. Что произойдет, если кому-то понадобится удалить 40,0000 записей одновременно. Вы могли бы заблокировать родительскую и все дочерние таблицы, возможно, на несколько минут, а иногда и часов, пока он работает и работает.

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

0 голосов
/ 09 февраля 2010

Вы просто должны установить правила ON DELETE CASCADE для внешних ключей.

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