Sql 多行更新触发器
我的触发器有问题:Sql 多行更新触发器,sql,sql-server,tsql,sql-server-2008,triggers,Sql,Sql Server,Tsql,Sql Server 2008,Triggers,我的触发器有问题: ALTER TRIGGER [dbo].[trg_B_U_Login] ON [dbo].[Login] FOR UPDATE AS BEGIN IF @@ROWCOUNT = 0 RETURN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON;
ALTER TRIGGER [dbo].[trg_B_U_Login]
ON [dbo].[Login]
FOR UPDATE
AS
BEGIN
IF @@ROWCOUNT = 0
RETURN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @Campos nvarchar(500);
DECLARE @Old_DataRemocao nvarchar(20);
DECLARE @New_DataRemocao nvarchar(20);
DECLARE @Old_IDCriador nvarchar(10);
DECLARE @New_IDCriador nvarchar(10);
SELECT @Campos='';
IF(Exists(SELECT * FROM deleted WHERE DataRemocao is NULL))
BEGIN
SELECT @Old_DataRemocao='NULL';
END
ELSE
BEGIN
SELECT @Old_DataRemocao=(SELECT * DataRemocao FROM deleted);
END
IF(Exists(SELECT * FROM inserted WHERE DataRemocao is NULL))
BEGIN
SELECT @New_DataRemocao=NULL;
END
ELSE
BEGIN
SELECT @New_DataRemocao=(SELECT * DataRemocao FROM inserted);
END
IF(@Old_DataRemocao<>@New_DataRemocao)
BEGIN
SELECT @Campos=@Campos+'DataRemocao={'+@Old_DataRemocao+' -> ' + @New_DataRemocao +'}; ';
END
IF(EXISTS(SELECT * FROM deleted as del, inserted AS ins WHERE ins.Login<>del.Login))
BEGIN
SELECT @Campos=@Campos+'Login={'+ del.Login +' -> '+ ins.Login+'}; ' FROM deleted as del, inserted as ins
END
......
IF(EXISTS(SELECT * FROM deleted as del, inserted AS ins WHERE ins.DataCriacao<>del.DataCriacao))
BEGIN
SELECT @Campos=@Campos+'DataCriacao={'+ del.DataCriacao +' -> '+ ins.DataCriacao+'}; ' FROM deleted as del, inserted as ins
END
IF(EXISTS(SELECT * FROM deleted as del, inserted AS ins WHERE ins.Nome<>del.Nome))
BEGIN
SELECT @Campos=@Campos+'Nome={'+ del.Nome +' -> '+ ins.Nome+'}; ' FROM deleted as del, inserted as ins
END
IF(@Campos<>'')
BEGIN
INSERT Login_Hs (IDUtilizador, Tabela, Metodo, Chave, Campos, Data)
SELECT '1', 'Login', 'UPDATE', 'IDLogin='+Convert(nvarchar,ID),
@Campos, CONVERT(DATETIME, GETDATE(), 105)
FROM inserted
END
END
正在更新多行
sql server 2008出现以下错误:
Msg 512, Level 16, State 1, Procedure trg_B_U_Login, Line 83
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
Msg 512,第16级,状态1,程序trg\U B\U\U登录,第83行
子查询返回了多个值。当子查询在=、!=、=或者当子查询用作表达式时。
声明已终止。
这只在我更新一行时起作用。
我该怎么做才能解决这个问题呢?好吧,您正试图在一个潜在的多值查询中捕获一个值。其中一个地方如下:
SELECT @Old_DataRemocao=(SELECT * DataRemocao FROM deleted);
更新:
鉴于您最近的评论,我想补充一点,您需要尝试以下方法来审核登录表的更改:
insert into Login_Hs (columns)
select i.col1, i.col2, ..., i.colN
FROM inserted i
我看到两个问题
ALTER TRIGGER [dbo].[trg_B_U_Login]
ON [dbo].[Login]
FOR UPDATE
AS
BEGIN
INSERT Login_Hs (IDUtilizador, Tabela, Metodo, Chave, Campos, Data)
SELECT '1', 'Login', 'UPDATE', 'IDLogin='+Convert(nvarchar,ID),
'DataRemocao={'+ coalesce(deleted.campos, 'NULL') + ' -> '
+ coalesce(inserted.campos, 'NULL'),
CONVERT(DATETIME, GETDATE(), 105)
FROM inserted
Inner Join deleted on inserted.idcol=deleted.idcol
END;
感谢@Bill
我做到了,而且成功了!ID、Login、PassWord、IDHomePage、IDSkin、IDPerfil、IDCriador、Email、DataCriacao、DataRemocao、Nome是我的表登录的字段,我保存它们
插入登录页面(IDUtilizador、Tabela、Metodo、Chave、Campos、Data)
选择“1”、“登录”、“更新”、“ID=”+转换(nvarchar,i.ID),
'Login={'+Convert(nvarchar,coalesce(d.Login,'NULL'))+'->'+Convert(nvarchar,coalesce(i.Login,'NULL'))+'};'+
'PassWord={'+coalesce(d.PassWord,'NULL')+'->'+coalesce(i.PassWord,'NULL')+'};'+
'IDHomePage={'+Convert(nvarchar,coalesce(d.IDHomePage,'NULL'))+'->'+Convert(nvarchar,coalesce(i.IDHomePage,'NULL'))+'};'+
'IDPerfil={'+Convert(nvarchar,coalesce(d.IDPerfil,'NULL'))+'->'+Convert(nvarchar,coalesce(i.IDPerfil,'NULL'))+'};'+
'IDCriador={'+Convert(nvarchar,coalesce(d.IDCriador,'NULL'))+'->'+Convert(nvarchar,coalesce(i.IDCriador,'NULL'))+'};'+
'Email={'+coalesce(d.Email,'NULL')+'->'+coalesce(i.Email,'NULL')+'};'+
'DataCriacao={'+coalesce(Convert(varchar(20),d.DataCriacao,105),'NULL')+'->'+coalesce(Convert(varchar(20),i.DataCriacao,105),'NULL')+'};'+
'DataRemocao={'+coalesce(Convert(varchar(20),d.DataRemocao,105),'NULL')+'->'+coalesce(Convert(varchar(20),i.DataRemocao,105),'NULL')+'};'+
'Nome={'+coalesce(d.Nome,'NULL')+'->'+coalesce(i.Nome,'NULL')+'};',
转换(DATETIME,GETDATE(),105)
从插入i
i.ID=d.ID上删除的内部联接d
有没有办法只保存不同的行?忘记告诉我要将每行中所做的所有更改保存到另一个表中,即“基于集合的语句”,对吗?我搜索解决方案,我发现了,但我不知道如何使用它。因此,不要使用我的插入,对吗?还有一个问题,如果我只想保存更改的数据?@SlimBoy
inserted
是正在插入的新数据,deleted
是旧数据,即被新数据替代;当然你可以加入他们,发现他们之间的差异,或者你能告诉我怎么做吗?我正在尝试这样做,如果(存在(选择*作为ins.ID=del.ID中ins.PassWorddel.PassWord作为ins插入的del-internal-JOIN)开始选择@Campos=@Campos+'PassWord={'+del.PassWord+'->'+ins.PassWord+'};'从deleted as del internal JOIN insert as ins ON ins.ID=del.ID END但它不起作用……我认为最好的做法是将已更改行的旧版本存储在历史记录表中,并在报表生成器中进行处理,或者创建xslt转换,该转换将完成清除这些数据并检测对这些数据的更改的工作输出到最终用户。
ALTER TRIGGER [dbo].[trg_B_U_Login]
ON [dbo].[Login]
FOR UPDATE
AS
BEGIN
INSERT Login_Hs (IDUtilizador, Tabela, Metodo, Chave, Campos, Data)
SELECT '1', 'Login', 'UPDATE', 'IDLogin='+Convert(nvarchar,ID),
'DataRemocao={'+ coalesce(deleted.campos, 'NULL') + ' -> '
+ coalesce(inserted.campos, 'NULL'),
CONVERT(DATETIME, GETDATE(), 105)
FROM inserted
Inner Join deleted on inserted.idcol=deleted.idcol
END;