2017-02-14 4 views
3

У меня есть таблица комментариев, которая является самореференцией. Я пытался писать на удаления каскада, но это займет некоторое исключениеОб удалении каскада для таблицы саморегуляции

Introducing FOREIGN KEY constraint 'FK_Comments_Comments' on table 'Comments' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

, а затем попытаться написать триггер, но обижаться снова

CREATE TRIGGER [dbo].[T_comment_Trigger] 
    ON [dbo].[Comments] 
    FOR DELETE 
AS 
    DELETE FROM Comments 
    WHERE ParentId =(SELECT deleted.id FROM deleted) 

couldn't delete rows that have children

, как я могу сделать при удалении каскаде мой личный справочник?

+2

Было бы очень полезно, если вы * обратили внимание * сообщения об ошибках и * скопировал свой текст в вопрос *, а не просто сказал «он принимает исключение». –

+0

У вашего триггера есть серьезная проблема. Предполагается, что только одна строка будет удалена. Вам нужно использовать соединение для этого типа вещей. –

+0

@Damien_The_Unbeliever Я редактирую свой вопрос – Mike

ответ

6

Предполагая, что вы держите свое ограничение FOREIGN KEY на месте, вы не можете исправить проблему в триггере FOR DELETE. FOR триггеры (также известные как AFTER триггеры) пожар после деятельность. И внешний ключ будет предотвратить строку, которую удаляют, если она имеет ссылки. Проверяются внешние ключи до удаление.

Для чего нужен триггер INSTEAD OF. Вы также должны иметь в виду, что ваш текущий триггер попытался разобраться с одним «уровнем» ссылок. (Таким образом, если строка 3 ссылки строка 2 и строка 2 ссылки строка 1, и удалить строку 1, триггер только попытался удалить строку 2)

Так, что-то вроде:

CREATE TRIGGER [dbo].[T_comment_Trigger] 
    ON [dbo].[Comments] 
    INSTEAD OF DELETE 
AS 
    ;WITH IDs as (
     select id from deleted 
     union all 
     select c.id 
     from Comments c 
       inner join 
      IDs i 
       on 
       c.ParentID = i.id 
    ) 
    DELETE FROM Comments 
    WHERE id in (select id from IDs); 

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

CREATE TRIGGER [dbo].[T_comment_Trigger] 
    ON [dbo].[Comments] 
    INSTEAD OF DELETE 
AS 
    declare @deletions table (ID varchar(7) not null); 
    ;WITH IDs as (
     select id from deleted 
     union all 
     select c.id 
     from Comments c 
       inner join 
      IDs i 
       on 
       c.ParentID = i.id 
    ) 
    insert into @deletions(ID) 
    select ID from IDs 

    DELETE FROM OtherTable 
    WHERE CommentID in (select ID from @deletions) 

    --This delete comes last 
    DELETE FROM Comments 
    WHERE id in (select ID from @deletions); 
+0

Ошибка: ** Невозможно создать INSTEAD OF DELETE или INSTEAD OF UPDATE TRIGGER 'T_comment_Trigger' на столе 'dbo.Comments'. Это связано с тем, что таблица имеет FOREIGN KEY с каскадным DELETE или UPDATE. ** возникает – Mike

+0

@Mike - вам нужно удалить * все * каскадные внешние ключи и реализовать все каскады вручную внутри этого триггера. (У вас все еще есть FK, а не опция каскада) –

+0

** В моей таблице есть 'on cascade delete' для других внешних ключей ** – Mike