Проблемы с триггером каскадного удаления
От: spy__  
Дата: 12.12.11 13:23
Оценка:
Добрый день.

У меня есть MS SQL 2008 и табличка такого плана:

create table Table4
(
id integer not null identity(1, 1) constraint PK_Table4_1 primary key,
x integer constraint FK_Table4_2 references Table4(id) on delete no action on update no action
);


Данные в ней, скажем, такие:

id | x
2 | null
3 | 2
4 | 2
5 | 2


Под все это дело я хочу организовать триггер для удаления записей. На данный момент родил такую штуку:

create trigger casc_table4_1 on Table4 instead of delete as
begin
delete from Table4 WHERE x in (select id from deleted)
end;


Проблема в том, что если выполнить запрос
delete from Table4 where id = 2;

то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?
cascade delete trigger
Re: Проблемы с триггером каскадного удаления
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 12.12.11 13:38
Оценка:
Здравствуйте, spy__, Вы писали:

__>Проблема в том, что если выполнить запрос

__>
__>delete from Table4 where id = 2;
__>

__>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[2]: Проблемы с триггером каскадного удаления
От: spy__  
Дата: 12.12.11 13:46
Оценка:
Здравствуйте, Sshur, Вы писали:

S>Здравствуйте, spy__, Вы писали:


__>>Проблема в том, что если выполнить запрос

__>>
__>>delete from Table4 where id = 2;
__>>

__>>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

S>Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.


1. for/after я уже пробовал. При выполнении запроса на удаление:

Сообщение 547, уровень 16, состояние 0, строка 1
Конфликт инструкции DELETE с ограничением SAME TABLE REFERENCE "FK_TABLE4_2". Конфликт произошел в базе данных "TEST1", таблица "dbo.Table4", column 'x'.
Выполнение данной инструкции было прервано.

Это подкидывает свинью наличие FK.

2. "Удаляйте руками". Можно конкретный пример? Т.к. у меня само создание триггера ругается на то, что не удается обновить deleted и inserted (это когда пробую выполнить больше одного запроса в триггере).
Re: Проблемы с триггером каскадного удаления
От: Аноним  
Дата: 12.12.11 13:54
Оценка: 3 (1)
Здравствуйте, spy__, Вы писали:

_>Проблема в том, что если выполнить запрос

__>
__>delete from Table4 where id = 2;
__>

__>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

Тело триггера по идее должно быть таким:
begin
    delete from Table4 WHERE x in (select id from deleted)
    delete from Table4 WHERE id in (select id from deleted)
end;
Re[3]: Проблемы с триггером каскадного удаления
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 12.12.11 13:55
Оценка: 3 (1)
Здравствуйте, spy__, Вы писали:


S>>Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.


__>1. for/after я уже пробовал. При выполнении запроса на удаление:

__>

Сообщение 547, уровень 16, состояние 0, строка 1
__>Конфликт инструкции DELETE с ограничением SAME TABLE REFERENCE "FK_TABLE4_2". Конфликт произошел в базе данных "TEST1", таблица "dbo.Table4", column 'x'.
__>Выполнение данной инструкции было прервано.

__>Это подкидывает свинью наличие FK.


Ну да. Вообще имхо плохая идея делать такое каскадное удаление через триггер. Надо сначала удалить все записи, на которые есть FK, а потом PK


__>2. "Удаляйте руками". Можно конкретный пример? Т.к. у меня само создание триггера ругается на то, что не удается обновить deleted и inserted (это когда пробую выполнить больше одного запроса в триггере).


Как-то так




create trigger casc_table4_1 on Table4 instead of delete as
begin
delete from Table4 WHERE x in (select id from deleted)

delete from Table4 WHERE id in (select id from deleted)
end;


У меня пример прошел успешно
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[4]: Проблемы с триггером каскадного удаления
От: spy__  
Дата: 12.12.11 14:11
Оценка:
Аноним, Sshur, благодарю, господа. Это рабочий вариант.

Вообще очень мутные вещи творятся с этими FK и триггерами. Т.е. таким же образом (instead of) нужно поступать и в ситуации, когда есть вторая таблица с not null FK на id первой таблицы: удалять сначала из второй, а потом и из первой.
Re[5]: Проблемы с триггером каскадного удаления
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 12.12.11 14:33
Оценка:
Здравствуйте, spy__, Вы писали:

__>Аноним, Sshur, благодарю, господа. Это рабочий вариант.


__>Вообще очень мутные вещи творятся с этими FK и триггерами. Т.е. таким же образом (instead of) нужно поступать и в ситуации, когда есть вторая таблица с not null FK на id первой таблицы: удалять сначала из второй, а потом и из первой.



Для второй таблицы на FK можно поставить on cascade delete

Если вы все чистите, то можно временно "выключить" связь (alter table nocheck constaraint ...)
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[6]: Проблемы с триггером каскадного удаления
От: spy__  
Дата: 12.12.11 14:37
Оценка:
S>Для второй таблицы на FK можно поставить on cascade delete

S>Если вы все чистите, то можно временно "выключить" связь (alter table nocheck constaraint ...)


Можно, но, к сожалению, не везде. В некоторых случаях MS SQL ругается на появление множественных каскадных путей, а исправлять структуру БД нельзя.
Re[7]: Проблемы с триггером каскадного удаления
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 12.12.11 14:51
Оценка:
Здравствуйте, spy__, Вы писали:

S>>Для второй таблицы на FK можно поставить on cascade delete


S>>Если вы все чистите, то можно временно "выключить" связь (alter table nocheck constaraint ...)


__>Можно, но, к сожалению, не везде. В некоторых случаях MS SQL ругается на появление множественных каскадных путей, а исправлять структуру БД нельзя.


Ну да. Эта проверка на каскадное удаление в MS SQL меня тоже иногда раздражает
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.