2010-03-03 3 views
5

У меня есть таблица SQL, определенная как показано ниже:Композитных первичные ключи и внешние ключи Ошибка ограничения

CREATE TABLE [TestComposite] ( 
    ID int, 
    SiteUrl nvarchar(255), 
    Name nvarchar(max) NOT NULL, 
    ParentID int NULL, 
    PRIMARY KEY (ID, SiteUrl) 
); 

товаров и папки, которые хранятся в той же таблицу, если элемент находится внутри папки, столбец ParentID является ID папки. И я хотел бы иметь возможность удалять элементы/папки CASCADE при удалении папки.

Примером может быть более явным:

INSERT INTO [TestComposite] VALUES (1, 'site1', 'Item1', NULL) 
INSERT INTO [TestComposite] VALUES (2, 'site1', 'Item2', NULL) 
INSERT INTO [TestComposite] VALUES (3, 'site1', 'Folder1', NULL) 
INSERT INTO [TestComposite] VALUES (4, 'site1', 'Folder1.Item1', 3) 
INSERT INTO [TestComposite] VALUES (5, 'site1', 'Folder1.Item2', 3) 
INSERT INTO [TestComposite] VALUES (6, 'site1', 'Folder1.Folder1', 3) 
INSERT INTO [TestComposite] VALUES (7, 'site1', 'Folder1.Folder1.Item1', 6) 
etc... 

Так, если удалить пункт 3 (папка), я хочу те элементы/папки 4, 5, 6 и 7, которые будут удалены тоже.

Я пытался добавить ограничение, похожее на:

ALTER TABLE [TestComposite] 
ADD CONSTRAINT fk_parentid 
FOREIGN KEY (ParentID, SiteUrl) 
REFERENCES [TestComposite] (ID, SiteUrl) ON DELETE CASCADE; 

Но это дает мне эту ошибку:
Вводя ограничение FOREIGN KEY «fk_parentid» на столе «TestComposite» может вызвать циклы или несколько путей порогов. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

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

Я делаю что-то неправильно?

Спасибо,

ответ

5

Создание ON DELETE NO ACTION ограничения и использовать это, чтобы удалить все записи и их ребенок:

WITH q AS 
     (
     SELECT id, SiteURL 
     FROM TestComposite 
     WHERE id = 3 
       AND SiteURL = 'site1' 
     UNION ALL 
     SELECT tc.id, tc.SiteURL 
     FROM q 
     JOIN TestComposite tc 
     ON  tc.ParentID = q.Id 
       AND tc.SiteURL = q.SiteURL 
     ) 
DELETE 
FROM TestComposite 
WHERE EXISTS 
     (
     SELECT id, SiteURL 
     INTERSECT 
     SELECT * 
     FROM q 
     ) 
+0

Возможно, я ошибаюсь, поскольку я еще не тестировал его, но я не думаю, что он удалит элемент 7 в моем случае, так как он находится на другом уровне иерархии?! –

+0

'@ OmaR': да, он также удалит' 7'. Это рекурсивный «CTE». – Quassnoi

+0

Спасибо, он отлично работает. Я не знал о рекурсивном CTE. И похоже, что он работает как на SQL Server 2005, так и на SQL Server 2008. –

0

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

+0

К сожалению, я не понимаю, что вы хотите мне делать ?! –

0

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

http://support.microsoft.com/kb/321843

+0

Как я сказал Ардману, если у меня нет составного первичного ключа, скажем только ID, я бы смог создать рекурсивный внешний ключ без проблем. CREATE TABLE myTable (ID int PRIMARY KEY, имя nvarchar (max), ParentID int); ALTER TABLE myTable ADD CONSTRAINT fk_parentID FOREIGN KEY (ParentID) ССЫЛКИ myTable (ID) ON CASCADE DELETE; Нет?! –

+0

нет, вы не можете! Я просто попытался. это не о составном ключе или нет, речь идет о том, что вы можете создать рекурсию на каскаде, и сервер sql не хочет делать это сам – Andrey

+0

Это странно, я бы поклялся, что я уже сделал это ... Я снова проверю его :) –

1

Если у вас есть SQL Server 2008, использовать из HierarchyID типа для этой работы.

+0

Спасибо, я попробую это –

+0

ваш приветственный OmaR. –

 Смежные вопросы

  • Нет связанных вопросов^_^