Объявление начала и конца локальной области (изменение нескольких триггеров в одной транзакции) - PullRequest
0 голосов
/ 27 марта 2012

Цель

Мне нужно изменить количество почти идентичных триггеров для нескольких таблиц (и нескольких баз данных).Поэтому я не хочу делать один большой сценарий и выполнять все изменения в одной транзакции с успехом или неудачей.

Моя первая попытка (это не работает)

---First alter trigger
ALTER TRIGGER [dbo].[trg_UserGarbleValue] ON [dbo].[users]
FOR INSERT
AS
Begin
    DECLARE @GarbleValue NVARCHAR(200)
    DECLARE @NewID NVARCHAR(20)

    SET @NewID = (SELECT TOP 1 usr_id FROM users ORDER BY usr_id DESC)

    SET @GarbleValue = dbo.fn_GetRandomString(4) + @NewID + dbo.fn_GetRandomString(4)

    UPDATE users SET usr_garble_value = @GarbleValue WHERE usr_id = @NewID
End
Go

--Subsequent alter trigger (there would be many more in the real-world usage)
ALTER TRIGGER [dbo].[trg_SegmentGarbleValue] ON [dbo].[segment]
FOR INSERT
AS
Begin
    DECLARE @GarbleValue NVARCHAR(200)
    DECLARE @NewID NVARCHAR(20)

    SET @NewID = (SELECT TOP 1 seg_id FROM segment ORDER BY seg_id DESC)

    SET @GarbleValue = dbo.fn_GetRandomString(4) + @NewID + dbo.fn_GetRandomString(4)

    UPDATE segment SET seg_garble_value = @GarbleValue WHERE seg_id = @NewID
End
Go

Запуск каждого из операторов alter trigger работает нормально.Но когда они оба выполняются в одной и той же транзакции, объявляется сбой во втором преобразователе, потому что имя переменной уже существует.

Как мне это сделать?Можно ли как-то объявить переменную локально в области начала или конца, или мне нужно полностью ее переосмыслить?умно, но это другое дело)

1 Ответ

0 голосов
/ 27 марта 2012

Я думаю, что вы перепутали GO (разделитель пакетов) и транзакции.Он не должен жаловаться на то, что имена переменных повторно объявлены, при условии, что разделители пакетов все еще присутствуют:

BEGIN TRANSACTION
GO
ALTER TRIGGER [dbo].[trg_UserGarbleValue] ON [dbo].[users]
FOR INSERT
AS
---Etc
Go
ALTER TRIGGER [dbo].[trg_SegmentGarbleValue] ON [dbo].[segment]
FOR INSERT
AS
---Etc
Go
COMMIT

Что касается вашего примечания о TOP 1, оно хуже, чем вы думаете - триггер запускаетсяодин раз на оператор , а не один раз на строку - он может выполняться в ответ на вставку нескольких строк.И, к счастью, существует псевдотаблица (называемая inserted), которая содержит именно те строки, которые вызвали срабатывание триггера - вам не нужно искать эти строки в базовой таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...