插入更新触发器如何确定是插入还是更新


162

我需要在表A上编写一个插入,更新触发器,该操作将从表B的所有行中删除所有行,该表的某一列(例如Desc)的值类似于在表A的列中插入/更新的值(例如Col1)。我将如何编写它,以便同时处理Update和Insert案例。我将如何确定是否为更新或插入执行了触发器。

Answers:


167

触发器具有特殊的INSERTEDDELETED表来跟踪“之前”和“之后”数据。因此,您可以使用类似的方法IF EXISTS (SELECT * FROM DELETED)来检测更新。DELETED更新时您只有行,但中总是有行INSERTED

CREATE TRIGGER中查找“插入” 。

编辑,2011年11月23日

评论后,此答案仅适用于INSERTEDUPDATED触发。
显然,INSERTED正如我在上文所述,DELETE触发器不能“始终有行”


查看下面的@MikeTeeVee答案以获得完整答案。这是不完整的。
洛伦兹·迈耶

1
@LorenzMeyer原始问题不需要那个。我也有EXISTS(SELECT * FROM DELETED)。不知道为什么您认为它不完整...
gbn

@LorenzMeyer也可能指的是语句“ 更新时您只有DELETED中的行,但INSERTED 中总有行。 ”这并不总是正确的,因为有时会调用Update / Insert触发器,而INSERTED为空的。在我的回答中,我解释了谓词消除任何数据更改不会引起的原因。在这种情况下,仍将为DML尝试调用触发器,但是DELETED和INSERTED表为空。这是因为当您要记录每个DML尝试(即使它们不更改任何数据)时,SQL仍然占时间。
MikeTeeVee

127
CREATE TRIGGER dbo.TableName_IUD
ON dbo.TableName
AFTER INSERT, UPDATE, DELETE
AS 
BEGIN
    SET NOCOUNT ON;

    --
    -- Check if this is an INSERT, UPDATE or DELETE Action.
    -- 
    DECLARE @action as char(1);

    SET @action = 'I'; -- Set Action to Insert by default.
    IF EXISTS(SELECT * FROM DELETED)
    BEGIN
        SET @action = 
            CASE
                WHEN EXISTS(SELECT * FROM INSERTED) THEN 'U' -- Set Action to Updated.
                ELSE 'D' -- Set Action to Deleted.       
            END
    END
    ELSE 
        IF NOT EXISTS(SELECT * FROM INSERTED) RETURN; -- Nothing updated or inserted.

    ...

    END

1
我喜欢写SELECT 1 FROM插入过,因为我觉得它发出信号的意图更加明确,但我会用MSSQL程序员disapointed如果这使得在这方面有什么区别...
卢卡斯·兰斯基

26
IF EXISTS(SELECT * ...)和IF EXISTS(SELECT 1)...具有完全相同的性能。完全不读取也不提取该行。实际上,您也可以使用IF EXISTS(SELECT 1/0 ...),它将仍然有效,并且不会导致被零除的错误。
Endrju 2014年

1
我正在为插入,更新和删除创建单独的触发器。现在很高兴知道它们可以组合!
UJS

2
如果有人将查询写到INSERT和DELETE两个不同的行(在同一脚本中插入新行并删除另一行),按上述方式设置的触发器是否可能实际上将其标识为UPDATE(即使意图是实际上不是更新),因为在插入/删除的sql表中有数据?
mche

87

如果您运行不删除任何内容的delete语句,则许多建议都不会考虑在内。
假设您尝试删除ID等于表中不存在的某个值的地方。
您的触发器仍然被调用,但是“已删除”或“插入”表中没有任何内容。

为了安全起见,请使用以下命令:

--Determine if this is an INSERT,UPDATE, or DELETE Action or a "failed delete".
DECLARE @Action as char(1);
    SET @Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
                         AND EXISTS(SELECT * FROM DELETED)
                        THEN 'U'  -- Set Action to Updated.
                        WHEN EXISTS(SELECT * FROM INSERTED)
                        THEN 'I'  -- Set Action to Insert.
                        WHEN EXISTS(SELECT * FROM DELETED)
                        THEN 'D'  -- Set Action to Deleted.
                        ELSE NULL -- Skip. It may have been a "failed delete".   
                    END)

特别感谢@KenDog和@Net_Prog的回答。
我是根据他们的脚本构建的。


3
这一项是奖品,处理不存在的删除。干得好!
安德鲁•沃尔夫

6
我们也可能有一个不影响任何行的UPDATE(甚至不影响INSERT)。
拉兹万·索科尔

@AndrewWolfe?你在说什么?该问题专门指出“我需要在表A上编写一个插入,更新触发器”。与删除触发器无关。
ypercubeᵀᴹ

@ypercubeᵀᴹ抱歉,大约80%的触发器涵盖了所有三个时间。
安德鲁·沃尔夫

18

我正在使用以下内容,它还可以正确检测不删除任何内容的删除语句:

CREATE TRIGGER dbo.TR_TableName_TriggerName
    ON dbo.TableName
    AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;

    IF NOT EXISTS(SELECT * FROM INSERTED)
        -- DELETE
        PRINT 'DELETE';
    ELSE
    BEGIN
        IF NOT EXISTS(SELECT * FROM DELETED)
            -- INSERT
            PRINT 'INSERT';
        ELSE
            -- UPDATE
            PRINT 'UPDATE';
    END
END;

4
这个错误地检测到什么都不插入或什么都不更新的语句。
罗曼·佩卡

11

经过大量搜索,我找不到单个SQL Server触发器的确切示例,该触发器可处理触发器动作INSERT,UPDATE和DELETE的所有(3)三个条件。我终于找到一行文字,讨论当发生DELETE或UPDATE时,公共DELETED表将包含这两个动作的记录这一事实。根据这些信息,我然后创建了一个小的Action例程,该例程确定了为什么激活了触发器。当在INSERT与UPDATE触发器上同时进行通用配置和特定操作时,有时需要这种类型的接口。在这些情况下,为UPDATE和INSERT创建单独的触发器将成为维护问题。(即,是否已针对必要的通用数据算法修复程序正确更新了两个触发器?)

为此,我想提供以下多触发事件代码段,用于在Microsoft SQL Server的一个触发器中处理INSERT,UPDATE,DELETE。

CREATE TRIGGER [dbo].[INSUPDDEL_MyDataTable]
ON [dbo].[MyDataTable] FOR INSERT, UPDATE, DELETE
AS 

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with caller queries SELECT statements.
-- If an update/insert/delete occurs on the main table, the number of records affected
-- should only be based on that table and not what records the triggers may/may not
-- select.
SET NOCOUNT ON;

--
-- Variables Needed for this Trigger
-- 
DECLARE @PACKLIST_ID varchar(15)
DECLARE @LINE_NO smallint
DECLARE @SHIPPED_QTY decimal(14,4)
DECLARE @CUST_ORDER_ID varchar(15)
--
-- Determine if this is an INSERT,UPDATE, or DELETE Action
-- 
DECLARE @Action as char(1)
DECLARE @Count as int
SET @Action = 'I' -- Set Action to 'I'nsert by default.
SELECT @Count = COUNT(*) FROM DELETED
if @Count > 0
    BEGIN
        SET @Action = 'D' -- Set Action to 'D'eleted.
        SELECT @Count = COUNT(*) FROM INSERTED
        IF @Count > 0
            SET @Action = 'U' -- Set Action to 'U'pdated.
    END

if @Action = 'D'
    -- This is a DELETE Record Action
    --
    BEGIN
        SELECT @PACKLIST_ID =[PACKLIST_ID]
                    ,@LINE_NO = [LINE_NO]
        FROM DELETED

        DELETE [dbo].[MyDataTable]
        WHERE [PACKLIST_ID]=@PACKLIST_ID AND [LINE_NO]=@LINE_NO
    END
 Else
    BEGIN
            --
            -- Table INSERTED is common to both the INSERT, UPDATE trigger
            --
            SELECT @PACKLIST_ID =[PACKLIST_ID]
                ,@LINE_NO = [LINE_NO]
                ,@SHIPPED_QTY =[SHIPPED_QTY]
                ,@CUST_ORDER_ID = [CUST_ORDER_ID]
            FROM INSERTED 

         if @Action = 'I'
            -- This is an Insert Record Action
            --
            BEGIN
                INSERT INTO [MyChildTable]
                    (([PACKLIST_ID]
                    ,[LINE_NO]
                    ,[STATUS]
                VALUES
                    (@PACKLIST_ID
                    ,@LINE_NO
                    ,'New Record'
                    )
            END
        else
            -- This is an Update Record Action
            --
            BEGIN
                UPDATE [MyChildTable]
                    SET [PACKLIST_ID] = @PACKLIST_ID
                          ,[LINE_NO] = @LINE_NO
                          ,[STATUS]='Update Record'
                WHERE [PACKLIST_ID]=@PACKLIST_ID AND [LINE_NO]=@LINE_NO
            END
    END   

9

我相信嵌套ifs会造成一些混乱,并且:

扁平比嵌套更好[Python的禅宗]

;)

DROP TRIGGER IF EXISTS AFTER_MYTABLE

GO

CREATE TRIGGER dbo.AFTER_MYTABLE ON dbo.MYTABLE AFTER INSERT, UPDATE, DELETE 

AS BEGIN 

    --- FILL THE BEGIN/END SECTION FOR YOUR NEEDS.

    SET NOCOUNT ON;

    IF EXISTS(SELECT * FROM INSERTED)  AND EXISTS(SELECT * FROM DELETED) 
        BEGIN PRINT 'UPDATE' END 
    ELSE IF EXISTS(SELECT * FROM INSERTED)  AND NOT EXISTS(SELECT * FROM DELETED) 
        BEGIN PRINT 'INSERT' END 
    ELSE IF    EXISTS(SELECT * FROM DELETED) AND NOT EXISTS(SELECT * FROM INSERTED)
        BEGIN PRINT 'DELETED' END
    ELSE BEGIN PRINT 'NOTHING CHANGED'; RETURN; END  -- NOTHING

END

9
Declare @Type varchar(50)='';
IF EXISTS (SELECT * FROM inserted) and  EXISTS (SELECT * FROM deleted)
BEGIN
    SELECT @Type = 'UPDATE'
END
ELSE IF EXISTS(SELECT * FROM inserted)
BEGIN
    SELECT @Type = 'INSERT'
END
ElSE IF EXISTS(SELECT * FROM deleted)
BEGIN
    SELECT @Type = 'DELETE'
END

5

试试这个..

ALTER TRIGGER ImportacionesGS ON dbo.Compra 
    AFTER INSERT, UPDATE, DELETE
AS
BEGIN
  -- idCompra is PK
  DECLARE @vIdCompra_Ins INT,@vIdCompra_Del INT
  SELECT @vIdCompra_Ins=Inserted.idCompra FROM Inserted
  SELECT @vIdCompra_Del=Deleted.idCompra FROM Deleted
  IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NULL)  
  Begin
     -- Todo Insert
  End
  IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NOT NULL)
  Begin
     -- Todo Update
  End
  IF (@vIdCompra_Ins IS NULL AND @vIdCompra_Del IS NOT NULL)
  Begin
     -- Todo Delete
  End
END

4

虽然我也喜欢@Alex发布的答案,但我在上面提供了@Graham解决方案的这种变化

与在第一个测试中使用COLUMNS_UPDATED相反,这专门使用了INSERTED和UPDATED表中的记录存在。知道已经考虑了最后一种情况,这也使程序员感到疑惑。

declare @action varchar(4)
    IF EXISTS (SELECT * FROM INSERTED)
        BEGIN
            IF EXISTS (SELECT * FROM DELETED) 
                SET @action = 'U'  -- update
            ELSE
                SET @action = 'I'  --insert
        END
    ELSE IF EXISTS (SELECT * FROM DELETED)
        SET @action = 'D'  -- delete
    else 
        set @action = 'noop' --no records affected
--print @action

您将通过以下语句获得NOOP:

update tbl1 set col1='cat' where 1=2

看来第一个END是缩进错误!(导致质疑第一个BEGIN关闭的位置)
S.Serpooshan

else if和final else包含单个语句。因为IF / Else是一个单独的语句,所以实际上没有必要开始和结束。我确实纠正了缩进。谢谢您的帮助。
greg

3

这可能是一种更快的方法:

DECLARE @action char(1)

IF COLUMNS_UPDATED() > 0 -- insert or update
BEGIN
    IF EXISTS (SELECT * FROM DELETED) -- update
        SET @action = 'U'
    ELSE
        SET @action = 'I'
    END
ELSE -- delete
    SET @action = 'D'

4
这种方法不适用于具有大量列的表,因为columns_updated()返回的varbinary很大。因此“ >>”失败了,因为0默认情况下是一个内部存储的数字,该数字比从columns_updated()返回的值小得多
Graham

3

所提供的两种解决方案的潜在问题是,取决于如何编写,更新查询可能会更新零个记录,而插入查询可能会插入零个记录。在这种情况下,插入和删除记录集将为空。在许多情况下,如果“插入”和“已删除”记录集均为空,则可能只想退出触发器而无需执行任何操作。


2

我在Grahams的其他不错的解决方案中发现了一个小错误:

应该为IF COLUMNS_UPDATED()< > 0-插入或更新
而不是> 0,这可能是因为最高位被解释为SIGNED整数符号位...(?)。因此总计:

DECLARE @action CHAR(8)  
IF COLUMNS_UPDATED() <> 0 -- delete or update?
BEGIN     
  IF EXISTS (SELECT * FROM deleted) -- updated cols + old rows means action=update       
    SET @action = 'UPDATE'     
  ELSE
    SET @action = 'INSERT' -- updated columns and nothing deleted means action=insert
END 
ELSE -- delete     
BEGIN
  SET @action = 'DELETE'
END

1

这对我有用:

declare @action_type int;
select @action_type = case
                       when i.id is not null and d.id is     null then 1 -- insert
                       when i.id is not null and d.id is not null then 2 -- update
                       when i.id is     null and d.id is not null then 3 -- delete
                     end
  from      inserted i
  full join deleted  d on d.id = i.id

由于并非一次可以更新所有列,因此您可以检查某个特定列是否正在通过以下方式进行更新:

IF UPDATE([column_name])

使用此解决方案的挑战是您必须知道列名。其他一些工具的设计使您仅可以从摘要库中复制粘贴。一点点,但考虑到所有因素,通用解决方案要比针对案例的解决方案好。恕我直言。
greg

1
declare @insCount int
declare @delCount int
declare @action char(1)

select @insCount = count(*) from INSERTED
select @delCount = count(*) from DELETED

    if(@insCount > 0 or @delCount > 0)--if something was actually affected, otherwise do nothing
    Begin
        if(@insCount = @delCount)
            set @action = 'U'--is update
        else if(@insCount > 0)
            set @action = 'I' --is insert
        else
            set @action = 'D' --is delete

        --do stuff here
    End

1
出于性能原因,我不会使用COUNT(*)-它需要扫描整个表。我将改为使用IF EXISTS(SELECT * FROM INSERTED)来设置标志,与DELETED相同。我知道通常只有几行受影响,但是为什么要减慢系统速度。
Endrju 2014年

我正准备发布一些非常相似的解决方案。它有点罗word,但非常可读。公平的权衡。我也喜欢上面的Grahms解决方案。
greg

1

我喜欢“计算机科学优雅”的解决方案。我的解决方案在这里分别命中[插入]和[删除]伪表以获取其状态,并将结果放入位映射变量中。然后,可以通过有效的二进制评估轻松地在整个触发器中测试INSERT,UPDATE和DELETE的每种可能组合(除非不太可能的INSERT或DELETE组合)。

它确实假设,如果不修改任何行,DML语句是什么无关紧要(这应满足绝大多数情况)。因此,尽管它不如Roman Pekar的解决方案完整,但效率更高。

通过这种方法,我们可以在每个表中使用一个“ FOR INSERT,UPDATE,DELETE”触发器,这使我们A)可以完全控制操作顺序,b)可以执行每个适用于多操作的代码。(显然,每个实现模型都有其优点和缺点;您将需要分别评估系统以找出最有效的方法。)

请注意,“存在(从插入/删除中选择*)”语句非常有效,因为没有磁盘访问权限(https://social.msdn.microsoft.com/Forums/en-US/01744422-23fe-42f6 -9ab0-a255cdf2904a)。

use tempdb
;
create table dbo.TrigAction (asdf int)
;
GO
create trigger dbo.TrigActionTrig
on dbo.TrigAction
for INSERT, UPDATE, DELETE
as
declare @Action tinyint
;
-- Create bit map in @Action using bitwise OR "|"
set @Action = (-- 1: INSERT, 2: DELETE, 3: UPDATE, 0: No Rows Modified 
  (select case when exists (select * from inserted) then 1 else 0 end)
| (select case when exists (select * from deleted ) then 2 else 0 end))
;
-- 21 <- Binary bit values
-- 00 -> No Rows Modified
-- 01 -> INSERT -- INSERT and UPDATE have the 1 bit set
-- 11 -> UPDATE <
-- 10 -> DELETE -- DELETE and UPDATE have the 2 bit set

raiserror(N'@Action = %d', 10, 1, @Action) with nowait
;
if (@Action = 0) raiserror(N'No Data Modified.', 10, 1) with nowait
;
-- do things for INSERT only
if (@Action = 1) raiserror(N'Only for INSERT.', 10, 1) with nowait
;
-- do things for UPDATE only
if (@Action = 3) raiserror(N'Only for UPDATE.', 10, 1) with nowait
;
-- do things for DELETE only
if (@Action = 2) raiserror(N'Only for DELETE.', 10, 1) with nowait
;
-- do things for INSERT or UPDATE
if (@Action & 1 = 1) raiserror(N'For INSERT or UPDATE.', 10, 1) with nowait
;
-- do things for UPDATE or DELETE
if (@Action & 2 = 2) raiserror(N'For UPDATE or DELETE.', 10, 1) with nowait
;
-- do things for INSERT or DELETE (unlikely)
if (@Action in (1,2)) raiserror(N'For INSERT or DELETE.', 10, 1) with nowait
-- if already "return" on @Action = 0, then use @Action < 3 for INSERT or DELETE
;
GO

set nocount on;

raiserror(N'
INSERT 0...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 0 object_id from sys.objects;

raiserror(N'
INSERT 3...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 3 object_id from sys.objects;

raiserror(N'
UPDATE 0...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t where asdf <> asdf;

raiserror(N'
UPDATE 3...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t;

raiserror(N'
DELETE 0...', 10, 1) with nowait;
delete t from dbo.TrigAction t where asdf < 0;

raiserror(N'
DELETE 3...', 10, 1) with nowait;
delete t from dbo.TrigAction t;
GO

drop table dbo.TrigAction
;
GO

感谢您提出的解决方案。您是否建议一种方法来更新已更新/插入的行的LastUpdated列?您还会建议一种在另一张表上存储已删除行的ID(可能由键组成)的方法吗?
塞巴斯蒂安

0

快速解决方案MySQL

顺便说一句:我正在使用MySQL PDO。

(1)在自动增量表中,每个脚本首先运行一次,只需从增量列中获取最大值(我的列名称= id):

$select = "
    SELECT  MAX(id) AS maxid
    FROM    [tablename]
    LIMIT   1
";

(2)像往常一样运行MySQL查询,并将结果转换为整数,例如:

$iMaxId = (int) $result[0]->maxid;

(3)在“ INSERT INTO ... ON DUPLICATE KEY UPDATE”查询之后,以您喜欢的方式获取最后插入的ID,例如:

$iLastInsertId = (int) $db->lastInsertId();

(4)比较并作出反应:如果lastInsertId高于表中的最高值,则可能是INSERT,对吗?反之亦然。

if ($iLastInsertId > $iMaxObjektId) {
    // IT'S AN INSERT
}
else {
    // IT'S AN UPDATE
}

我知道它很快,甚至很脏。这是一个旧帖子。但是,嘿,我长期以来一直在寻找解决方案,也许有人发现我的方式仍然很有用。祝一切顺利!


0

只是简单的方法

CREATE TRIGGER [dbo].[WO_EXECUTION_TRIU_RECORD] ON [dbo].[WO_EXECUTION]
WITH EXECUTE AS CALLER
FOR INSERT, UPDATE
AS
BEGIN  

  select @vars = [column] from inserted 
  IF UPDATE([column]) BEGIN
    -- do update action base on @vars 
  END ELSE BEGIN
    -- do insert action base on @vars 
  END

END 

根据我的SSMS IDE,您的语法与在IF BEGIN-END ELSE BEGIN-END块中包装逻辑的方式不正确。
Erutan409

0

在第一种情况下,我认为您的表具有IDENTITY列

CREATE TRIGGER [dbo].[insupddel_yourTable] ON [yourTable]
FOR INSERT, UPDATE, DELETE
AS
IF @@ROWCOUNT = 0 return
SET NOCOUNT ON;
DECLARE @action nvarchar(10)
SELECT @action = CASE WHEN COUNT(i.Id) > COUNT(d.Id) THEN 'inserted'
                      WHEN COUNT(i.Id) < COUNT(d.Id) THEN 'deleted' ELSE 'updated' END
FROM inserted i FULL JOIN deleted d ON i.Id = d.Id

在第二种情况下,不需要使用IDENTITTY列

CREATE TRIGGER [dbo].[insupddel_yourTable] ON [yourTable]
FOR INSERT, UPDATE, DELETE
AS
IF @@ROWCOUNT = 0 return
SET NOCOUNT ON;
DECLARE @action nvarchar(10),
        @insCount int = (SELECT COUNT(*) FROM inserted),
        @delCount int = (SELECT COUNT(*) FROM deleted)
SELECT @action = CASE WHEN @insCount > @delCount THEN 'inserted'
                      WHEN @insCount < @delCount THEN 'deleted' ELSE 'updated' END

我也遇到同样的问题,有人可以帮助我。请参阅以下链接stackoverflow.com/questions/26043106/...
拉梅什小号

0
DECLARE @INSERTEDCOUNT INT,
        @DELETEDCOUNT INT

SELECT @INSERTEDCOUNT = COUNT([YourColumnName]) FROM inserted

SELECT @DELETEDCOUNT = COUNT([YourColumnName]) FROM deleted

如果更新

 @INSERTEDCOUNT = 1
 @DELETEDCOUNT = 1

如果插入

 @INSERTEDCOUNT = 1
 @DELETEDCOUNT = 0

0

我已经使用这些exists (select * from inserted/deleted)查询很长时间了,但是对于空的CRUD操作(当insertedand deleted表中没有记录时)仍然不够。因此,在研究了这一主题后,我找到了更精确的解决方案:

declare
    @columns_count int = ?? -- number of columns in the table,
    @columns_updated_count int = 0

-- this is kind of long way to get number of actually updated columns
-- from columns_updated() mask, it's better to create helper table
-- or at least function in the real system
with cte_columns as (
    select @columns_count as n
    union all
    select n - 1 from cte_columns where n > 1
), cte_bitmasks as (
    select
        n,
        (n - 1) / 8 + 1 as byte_number,
        power(2, (n - 1) % 8) as bit_mask
    from cte_columns
)
select
    @columns_updated_count = count(*)
from cte_bitmasks as c
where
    convert(varbinary(1), substring(@columns_updated_mask, c.byte_number, 1)) & c.bit_mask > 0

-- actual check
if exists (select * from inserted)
    if exists (select * from deleted)
        select @operation = 'U'
    else
        select @operation = 'I'
else if exists (select * from deleted)
    select @operation = 'D'
else if @columns_updated_count = @columns_count
    select @operation = 'I'
else if @columns_updated_count > 0
    select @operation = 'U'
else
    select @operation = 'D'

也可以使用 columns_updated() & power(2, column_id - 1) > 0查看列是否已更新,但是对于具有大量列的表来说并不安全。我使用了一种复杂的计算方式(请参阅下面的帮助文章)。

同样,此方法仍会错误地将某些更新分类为插入(如果表中的每一列都受到更新的影响),并且可能会将仅默认值插入为删除的插入分类,但这些是罕见操作的王者(在租赁在我的系统中)。除此之外,我目前不知道如何改进此解决方案。


0
declare @result as smallint
declare @delete as smallint = 2
declare @insert as smallint = 4
declare @update as smallint = 6
SELECT @result = POWER(2*(SELECT count(*) from deleted),1) + POWER(2*(SELECT 
     count(*) from inserted),2)

if (@result & @update = @update) 
BEGIN
  print 'update'
  SET @result=0
END
if (@result & @delete = @delete)
  print 'delete'
if (@result & @insert = @insert)
  print 'insert'

0

我这样做:

select isnull((select top 1 1 from inserted t1),0) + isnull((select top 1 2 from deleted t1),0)

1->插入

2->删除

3->更新

set @i = isnull((select top 1 1 from inserted t1),0) + isnull((select top 1 2 from deleted t1),0)
--select @i

declare @action varchar(1) = case @i when 1 then 'I' when 2 then 'D' when 3 then 'U' end
--select @action


select @action c1,* from inserted t1 where @i in (1,3) union all
select @action c1,* from deleted t1 where @i in (2)

0
DECLARE @ActionType CHAR(6);
SELECT  @ActionType = COALESCE(CASE WHEN EXISTS(SELECT * FROM INSERTED)
                                     AND EXISTS(SELECT * FROM DELETED)  THEN 'UPDATE' END,
                               CASE WHEN EXISTS(SELECT * FROM DELETED)  THEN 'DELETE' END,
                               CASE WHEN EXISTS(SELECT * FROM INSERTED) THEN 'INSERT' END);
PRINT   @ActionType;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.