Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Каскадные обновления через триггер / 7 сообщений из 7, страница 1 из 1
04.04.2002, 07:29
    #32026921
ASCRUS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
Привет. Вопрос чисто академический - случайно столкнулся и заинтересовался. Вопрос такой - можно ли через триггер организовать поддержку каскадных обновлений, как это аппаратно поддерживается через CASCADE UPDATE ?
Например есть 2 таблицы:

\ncreate table Table1(Key_id int not null primary key)
create table Table2(Id int not null identity primary key, Key_id int not null)


При изменении Key_id в Table1 надо организовать изменение соответствующих Key_id в Table2 на новое значение:

\nupdate Table
set Key_id = 2
where Key_id = 1


При таком раскладе триггер выглядит просто:

\ncreate triger trg_Table1_Update on Table1 for update
as
if update(Key_id)
update t2
set Key_id = (select Key_id from Inserted)
from Table2 t2
inner join Deleted d on t2.Key_id = d.Key_id


Однако как написать триггер при таком варианте:

\nupdate Table
set Key_id = Key_id + 1


Получится, что таблицы Inserted и Deleted просто не с чем соединить, так как Key_id в них совпадать не будут. Какие будут предложения ?
...
Рейтинг: 0 / 0
04.04.2002, 10:18
    #32026950
Glory
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
IMHO

- если Key_id у вас первичный ключ в понятиях SQL-я, т.е. имеется уникальный индекс, то при AFTER триггерах вы не сможете сделать Key_id + 1 даже для одной записи, если уже имеется запись с таким значением.

- замену первичного ключа можно делать через промежуточное поле
...
Рейтинг: 0 / 0
04.04.2002, 16:18
    #32026997
ASCRUS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
Почему не могу ?

\ndeclare @T table (Id int not null primary key)

insert into @T values (1)
insert into @T values (2)
insert into @T values (3)

select *
from @T

update @T
set Id = Id + 1

select *
from @T


Прекрасно работает с изменением первичного ключа (лог-файл не только для отката транзакций существует ). А вот в моем примере в дочерней таблице Key_id не первичный ключ. Значит и там можно изменить. Так что вопрос остается в силе.

Я тут как решение попробовал такой способ:

\ncreate triger trg_Table1_Update on Table1 for update
as
if update(Key_id)
begin
declare @I table(Row_id int identity not null primary key, Key_id int not null)
declare @D table(Row_id int identity not null primary key, Key_id int not null)

insert into @I(Key_id)
select Key_id
from Inserted

insert into ID
select Key_id
from Deleted

update t2
set Key_id = i.Key_id
from Table2 t2
inner join @D d on t2.Key_id = d.Key_id
inner join @I i on d.Row_id = i.Row_id

end


Единственное что в этом решении не хорошо, что нет гарантии, что в таблицы @I и @D записи попадут под одинаковыми Row_id, хотя пока у меня все сработало. Какие еще будут предложения ? Никто не копал Inserted и Deleted поглубже ?

P.S. Повторяюсь - вопрос чисто теоретический, так как я в здравом уме и твердой памяти и менять Primary Key считаю признаком дурного тона. Просто для самообразования интересуюсь
...
Рейтинг: 0 / 0
05.04.2002, 08:05
    #32027048
Glory
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
У меня команда
create table Table1(Key_id int not null primary key)

приводит к созданию уникального индекса поэтому на

update Table1 set Key_id = 2 where Key_id = 1

выдается

Server: Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK__Table1__4865BE2A'. Cannot insert duplicate key in object 'Table1'.
The statement has been terminated.

и с таблицами-переменными тоже.

Массовое же изменение

update Table1 set Key_id = Key_id + 1

проходит (но вам-то оно как раз не нужно)



IMHO логичнее использовать INSTEAD триггеры
...
Рейтинг: 0 / 0
05.04.2002, 09:26
    #32027072
dmitry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
Возвращаясь к исходному вопросу и отвлекаясь от справедливых замечаний Glory оставляя контроль за значениями на ключ на совесть ASCRUS-а (например update Table set Key_id = Key_id + 10000), где изначально Key_id<10000,

замечу, что можно ведь не мудрствуя лукаво просто выполнить такое обновление в триггере в два этапа - просто
Delete from table2 from table2 join deleted on table2.key_id=deleted.key_id
insert into table2 select * from inserted

За исключением, конечно случаев с полями с identity (как в Table1, так и в Table2), но и эта проблема решаема с помощью identity_insert
...
Рейтинг: 0 / 0
05.04.2002, 17:37
    #32027109
ASCRUS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
Сапсибо - действительно красивое решение. Насчет ключа - я действительно от балды первое попавшееся в голову привел в пример.
...
Рейтинг: 0 / 0
05.04.2002, 17:38
    #32027110
ASCRUS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Каскадные обновления через триггер
Спасибо - действительно красивое решение. Насчет ключа - я действительно от балды первое попавшееся в голову привел в пример.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Каскадные обновления через триггер / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]