Каскадные удаления, вызывающие несколько каскадных путей
Я использую SQlServer 2008, и ниже приведены некоторые таблицы данных:
пользователей
Идентификатор (ПК)
UserItems
UserId (PK) ItemId (PK) - (составной ключ из 2 столбцов)...
UserItemVotes
UserId (PK) ItemId (PK) VoterId (PK) - (составной ключ из 3 столбцов)
У меня определены следующие отношения:
- User.Id -> UserItems.UserId
- (UserItems.UserId, UserItems.ItemId) -> (UserItemVotes.UserId, UserItemVotes.ItemId)
- UserId.Id -> UserItemVotes.VoterId
Теперь у меня проблема при включении каскадного удаления. При добавлении 3-го отношения я получаю сообщение об ошибке "... может вызвать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY". Я не очень хочу этого делать, в идеале, если пользователь будет удален, я бы хотел удалить его элемент пользователя и / или его голоса.
Это плохой дизайн? Или есть способ получить поведение, которое я хочу от SQL Server?
3 ответа
Я бы привел к плохому дизайну. Хотя большинство СУБД могут управлять каскадным удалением, использование этой встроенной функциональности рискованно. Ваш сценарий - прекрасный пример того, почему этими типами вещей часто управляют в коде приложения. Там вы можете точно определить, что нужно удалить и в каком порядке.
Утвержденный ответ не является хорошим ответом. Описанный сценарий не плохой дизайн, и при этом не "рискованно" полагаться на базу данных для выполнения своей работы.
Оригинальный вопрос описывает совершенно правильный сценарий, а дизайн хорошо продуман. Ясно, что удаление пользователя должно удалять как элементы пользователя (и любые голоса за них), так и удалять голоса пользователя за любой элемент (даже элементы, принадлежащие другим пользователям). Целесообразно попросить базу данных выполнить это каскадное удаление, когда удаляется запись пользователя.
Проблема в том, что SQL Server не может справиться с этим. Его реализация каскадных удалений несовершенна.
"UserItems.ItemId -> UserItemVotes.UserId"
Этот кажется крайне подозрительным.