在SQL Server中插入后触发器中未显示所有记录
我有一个表在SQL Server中插入后触发器中未显示所有记录,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我有一个表表1,其中包含一些数据: create table table1 ( c1 varchar(20), c2 varchar(20) ) insert into table1 values('1','A') insert into table1 values('2','B') insert into table1 values('3','C') insert into table1 values('4','D') insert into table1 values(
表1
,其中包含一些数据:
create table table1
(
c1 varchar(20),
c2 varchar(20)
)
insert into table1 values('1','A')
insert into table1 values('2','B')
insert into table1 values('3','C')
insert into table1 values('4','D')
insert into table1 values('5','E')
insert into table1 values('6','F')
现在,我创建了另一个具有相同结构的表,名为table2
:
create table table2
(
c1 varchar(20),
c2 varchar(20)
)
CREATE TRIGGER trgAfterInsert
ON [dbo].[table2]
FOR INSERT
AS
declare @c1 varchar(20);
declare @c2 varchar(20);
declare @audit_action varchar(100);
select @c1 = i.c1 from inserted i;
select @c2 = i.c2 from inserted i;
set @audit_action = 'Inserted Record -- After Insert Trigger.';
insert into table2_Audit(c1, c2, Audit_Action, Audit_Timestamp)
values(@c1, @c2, @audit_action, getdate());
PRINT 'AFTER INSERT trigger fired.'
GO
然后我在表2
上的Insert后创建了一个触发器:
create table table2
(
c1 varchar(20),
c2 varchar(20)
)
CREATE TRIGGER trgAfterInsert
ON [dbo].[table2]
FOR INSERT
AS
declare @c1 varchar(20);
declare @c2 varchar(20);
declare @audit_action varchar(100);
select @c1 = i.c1 from inserted i;
select @c2 = i.c2 from inserted i;
set @audit_action = 'Inserted Record -- After Insert Trigger.';
insert into table2_Audit(c1, c2, Audit_Action, Audit_Timestamp)
values(@c1, @c2, @audit_action, getdate());
PRINT 'AFTER INSERT trigger fired.'
GO
有一个问题,当我将table1
的所有数据复制到tabe2
时,审计表中只显示一条记录。它不会显示所有插入的记录
我使用此查询复制表2中的记录
:-
insert into table2(c1,c2) select c1,c2 from table1
触发器在整个操作中触发一次,请将代码更改为:
CREATE TRIGGER trgAfterInsert ON [dbo].[table2]
FOR INSERT
AS
BEGIN
DECLARE @audit_action VARCHAR(100) = 'Inserted Record -- After Insert Trigger.';
INSERT INTO table2_Audit(c1,c2,Audit_Action,Audit_Timestamp)
SELECT i.c1, i.c2, @audit_action, GETDATE()
FROM inserted i;
END
第二,不要在触发器内部使用PRINT
你看到的行为是故意的。sqlserver中的DML触发器
是语句级触发器-它们在
插入/更新/删除/合并,无论有多少行受到影响
通过DML语句。所以你应该把你的逻辑写在触发器里
处理插入/删除表中的多行
针对该表发出的每个insert语句触发一次触发器。表中插入的每一行没有一个。因此,若插入了多行,则触发器定义应该能够处理多行
不要使用变量从插入的表中捕获值,然后将它们插入表2中,只需从插入的表中选择并将数据插入表2中即可
处理此问题的触发器类似于
CREATE TRIGGER trgAfterInsert ON [dbo].[table2]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into table2_Audit (c1,c2,Audit_Action,Audit_Timestamp)
SELECT C1
, C2
, 'Inserted Record -- After Insert Trigger.'
, GETDATE()
FROM inserted ;
PRINT 'AFTER INSERT trigger fired.'
END
GO
这是完全正常的。为整个操作触发一次点火插入表2(c1,c2)从表1中选择c1,c2
不是每行。使用内部触发器插入表2\u审计(c1、c2、审计操作、审计时间戳)选择列。。。从插入代码>你的触发器有一个主要的缺陷,你似乎认为它每行调用一次——事实并非如此。每个语句触发一次触发器,因此如果INSERT
语句影响25行,则触发一次触发器,但Inserted
将包含25行。您的代码将在此处选择这25行中的哪一行<代码>从插入的i中选择@c1=i.c1代码>-这是不确定的,您可以得到一行任意行,其他24行都被忽略。你需要重写你的触发器来考虑这一点!