Несколько строк с SQL INSTEAD Триггера - PullRequest
0 голосов
/ 07 апреля 2020

Я смотрю немного направления или указания, почему я получаю несколько строк, используя мой триггер. В основном у меня есть веб-приложение, которое контролирует типы активов (например, ноутбуки, телефоны и т. Д. c), и я пытаюсь сделать с этим триггером, когда имя типа актива (at_typedes c) изменяется, и я записываюсь в аудит table (в данном случае sql_log), какое было старое имя и какое новое.

Это работает, но по какой-то причине я получаю несколько строк, написанных в операторе INSERT TO SQL_LOG. Он записывает старое имя и новое имя, но затем я получу еще 3 строки, в которых старое имя показывает новое имя ...

Это в настоящее время на сервере 2008 SQL.

-- create the trigger

go
create trigger trg_InsteadOfUpdate on [dbo].[lkp_asset_types]
instead of update
as

    begin

            DECLARE @triggerAction varchar(1)

            -- determine the TRIGGER action
            -- this allows us to tell if its an INSERT or an UPDATE
            SELECT @triggerAction = CASE
            WHEN EXISTS(SELECT 1 FROM INSERTED)
            AND EXISTS(SELECT 1 FROM deleted) THEN 'U'
            WHEN EXISTS(SELECT 1 FROM inserted) THEN 'I'
            ELSE 'D' END;

            -- get the orginally asset name from the DELETED table
            -- this contains the rows as they were BEFORE the UPDATE Statement
            DECLARE @orgAssetTypeName varchar(255)
            SET @orgAssetTypeName = (SELECT top 1 at_typedesc from lkp_asset_types WHERE at_id = (select at_id from deleted))

            -- UPDATE to the new asset name based on the NEW value in the INSERTED Table
            update lkp_asset_types
            set at_typedesc = (select at_typedesc from inserted)
            where at_id = (select at_id from inserted)

            -- get the new asset name from the INSERTED table
            -- this contains the rows as they were AFTER the UPDATE Statement
            DECLARE @newAssetTypeName varchar(255)
            SET @newAssetTypeName = (SELECT top 1 at_typedesc from lkp_asset_types WHERE at_id = (select at_id from inserted))

            insert into sql_log
            (sql_log)
            values ('SQL PRE Changed from : ' + @orgAssetTypeName + ' to: ' + @newAssetTypeName + '.  Action = ' + @triggerAction)

    end
go

Ответы [ 3 ]

1 голос
/ 07 апреля 2020

Logi c как в триггере в SQL Сервер просто сломан:

       where at_id = (select at_id from inserted)

Я действительно sh Анализатор SQL Server выдал предупреждение при обнаружении таких конструкций.

Нет никакой гарантии, что inserted имеет только одно значение (ни deleted).

Именно так SQL Сервер определяет триггеры: устанавливает операции , Если несколько строк вставляются одновременно, то у «таблиц» inserted и deleted есть несколько строк.

Эта часть проста. Вам нужно будет переписать триггер, чтобы учесть это.

0 голосов
/ 07 апреля 2020

При проверке моего веб-кода кнопка обновления выполняла дополнительные обновления, это вызывало срабатывание триггера более одного раза, что приводило к дублированию строк.

0 голосов
/ 07 апреля 2020
create table dbo.lkp_asset_types_test
(
at_id int identity,
at_typedesc varchar(100)
)
go

create trigger trg_InsteadOfUpdate_test on [dbo].[lkp_asset_types_test]
instead of update
as
begin

    select 'trigger fired!!!!'

    if not exists(select * from inserted)
    and not exists(select * from deleted)
    begin
        return;
    end

    --update (maybe only the diffs?)
    update t
    set at_typedesc = i.at_typedesc
    from dbo.lkp_asset_types_test as t
    join inserted as i on t.at_id = i.at_id;
    --where t.at_typedesc <> i.at_typedesc & nulls??

    --insert into sql_log(sql_log)
    select
        'SQL PRE Changed from : ' + isnull(d.at_typedesc, '*null*') + ' to: ' + isnull(i.at_typedesc, '*null*') + '.  Action = U'
    from inserted as i
    join deleted as d on i.at_id = d.at_id
    --where i.at_typedesc <> d.at_typedesc & nulls ??
end
go


insert into dbo.lkp_asset_types_test(at_typedesc) values ('A'), ('B'), ('C'), ('D'), (NULL);
go

update dbo.lkp_asset_types_test
set at_typedesc = case when at_id%2=0 then isnull(at_typedesc, 'X') else isnull(at_typedesc, '') + 'xyz' end
go

select *
from dbo.lkp_asset_types_test;
go

update dbo.lkp_asset_types_test
set at_typedesc = case when at_id%2=0 then at_typedesc else at_typedesc + 'xyz' end
where 1=2
go

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