在触发器的SQL INSTEAD中具有多个行

问题描述 投票:-1回答:3

关于我为什么使用触发器获得多行的一些指导或指导。基本上,我有一个控制资产类型(例如笔记本电脑,电话等)的Web应用程序,我要使用此触发器执行的操作是当资产类型名称(at_typedesc)更改为我登录到审核表时(在本例中为sql_log) )旧名称是什么,新名称是什么。

这是可行的,但是由于某种原因,我在INSERT TO SQL_LOG语句中写了多行。它的确写了旧名称和新名称,但随后我又得到了3行,其中有旧名称显示了新名称...

当前位于2008 SQL Server上。

-- 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
sql sql-server database-trigger
3个回答
1
投票

SQL Server触发器中的类似逻辑被破坏:

       where at_id = (select at_id from inserted)

我真的希望SQL Server解析器在遇到此类构造时发出警告。

无法保证inserted只有一个值(也没有deleted)。

这就是SQL Server将触发器定义为set操作的方式。如果同时插入多行,则inserteddeleted“表”具有多行。

这部分很简单。您需要重写触发器以考虑到这一点。


0
投票

在检查我的Web代码时,更新按钮正在执行其他更新,这导致触发器多次触发,从而导致重复的行。


-3
投票
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;
© www.soinside.com 2019 - 2024. All rights reserved.