powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Каскадные обновления через триггер
7 сообщений из 7, страница 1 из 1
Каскадные обновления через триггер
    #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
Каскадные обновления через триггер
    #32026950
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMHO

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

- замену первичного ключа можно делать через промежуточное поле
...
Рейтинг: 0 / 0
Каскадные обновления через триггер
    #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
Каскадные обновления через триггер
    #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
Каскадные обновления через триггер
    #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
Каскадные обновления через триггер
    #32027109
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сапсибо - действительно красивое решение. Насчет ключа - я действительно от балды первое попавшееся в голову привел в пример.
...
Рейтинг: 0 / 0
Каскадные обновления через триггер
    #32027110
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо - действительно красивое решение. Насчет ключа - я действительно от балды первое попавшееся в голову привел в пример.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Каскадные обновления через триггер
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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