Почему SQL Server не позволяет мне создавать эти внешние ключи? - PullRequest
1 голос
/ 31 марта 2011

Моя (сокращенная) схема имеет (или, скорее, потребует) следующие таблицы и взаимосвязи:

Clients (ID INT PRIMARY KEY)
Files (
    ID INT PRIMARY KEY,
    Client INT REFERENCES Clients(ID) ON DELETE CASCADE)
Interfaces (
    ID INT PRIMARY KEY,
    Client INT REFERENCES Clients(ID) ON DELETE CASCADE)
Files_Interfaces (
    "File" INT REFERENCES Files(ID) ON DELETE CASCADE,
    Interface INT REFERENCES Interfaces(ID) ON DELETE CASCADE)

Таким образом, как видно из этой схемы, клиент может иметь несколько файлов и несколько интерфейсов.Между интерфейсами и файлами существует отношение «многие ко многим» (отсюда и таблица соединений Files_Interfaces), и единственными иерархическими отношениями являются «Клиент» (существует отношение «один ко многим» от Clients до Files иInterfaces).

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

Проблема в том, что SQL Server 2005 не позволяет мне иметь эту схему.Когда я пытаюсь создать Files_Interfaces с такими ограничениями, я получаю следующую ошибку:

Введение ограничения FOREIGN KEY 'FK__Files_Int__Inter__3D2915A8' в таблицу 'Files_Interfaces' может вызывать циклы или несколько каскадных путей.Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

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

Можно ли как-то предотвратить эту ошибку?

1 Ответ

5 голосов
/ 31 марта 2011

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

Как и сейчас, SQL Server требует, чтобы каскадный граф былдерево, а не ориентированный ациклический (или, что еще хуже, циклический) граф:

Последовательность каскадных ссылочных действий, запускаемых одним DELETE или UPDATE, должна образовывать дерево, не содержащее циклических ссылок,Ни одна таблица не может появляться более одного раза в списке всех каскадных ссылочных действий, которые являются результатом DELETE или UPDATE.Кроме того, дерево каскадных ссылочных действий не должно иметь более одного пути к любой указанной таблице.Любая ветвь дерева заканчивается, когда встречается таблица, для которой было указано NO ACTION или по умолчанию.

Из-за ограничений реализации SQL Server не оптимизирует каскадное удаление как одинОперация, основанная на множестве, скорее, она разбивает дерево на серию отдельных объединений.В случае A -> B -> C, DELETE A - это не DELETE A JOIN B JOIN C, а DELETE A JOIN B OUTPUT B_temp, за которым следует DELETE B_temp JOIN C.

В случае нескольких каскадных путей это приведет к нескольким B_temp.

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