Sql server SQL Server:使用一个查询触发更新
我有一个触发器,当某些列被更新时,它会记录到审计表中。我在删除一列后使用更新的列时遇到了很多问题,所以我正在重写触发器只使用更新,这似乎很有效 但是,我在每个IF语句中不断重复查询,如果UpdateColumnName,请参见下面的代码,因为我需要动态更改列名。有没有办法欺骗我,这样我就不必重复插入查询了Sql server SQL Server:使用一个查询触发更新,sql-server,Sql Server,我有一个触发器,当某些列被更新时,它会记录到审计表中。我在删除一列后使用更新的列时遇到了很多问题,所以我正在重写触发器只使用更新,这似乎很有效 但是,我在每个IF语句中不断重复查询,如果UpdateColumnName,请参见下面的代码,因为我需要动态更改列名。有没有办法欺骗我,这样我就不必重复插入查询了 我不确定下面的性能,但您可以使用unpivot获得类似的效果 将任何审计表作为 CREATE TABLE dbo.AuditLog ( DatabaseName SYSN
我不确定下面的性能,但您可以使用unpivot获得类似的效果 将任何审计表作为
CREATE TABLE dbo.AuditLog
(
DatabaseName SYSNAME,
SchemaName SYSNAME,
TableName SYSNAME,
ColumnName SYSNAME,
KeyValue SQL_VARIANT,
OldValue SQL_VARIANT,
NewValue SQL_VARIANT,
TransactionType VARCHAR(10),
LogDate AS CURRENT_TIMESTAMP
)
GO
然后是要记录的“普通”表
CREATE TABLE dbo.MyTable
(
Id INT IDENTITY(1,1),
Col1 INT,
Col2 INT,
Col3 INT
)
GO
使用unpivot记录更改的触发器是
编辑以供评论:
IF @action = @UPDATED
BEGIN
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, upiv_inserted.ColumnName,
upiv_inserted.Id, upiv_deleted.OldValue, upiv_inserted.NewValue, 'UPDATE'
FROM (
SELECT ColumnName, Id, NewValue
FROM inserted
CROSS APPLY (
VALUES
('Col1', Col1),
('Col2', Col2)
) upiv (ColumnName, NewValue)
) upiv_inserted
JOIN (
SELECT ColumnName, Id, OldValue
FROM deleted
CROSS APPLY (
VALUES
('Col1', Col1),
('Col2', Col2)
) upiv (ColumnName, OldValue)
) upiv_deleted
ON upiv_deleted.Id = upiv_inserted.Id
AND upiv_deleted.ColumnName = upiv_inserted.ColumnName
WHERE upiv_deleted.OldValue <> upiv_inserted.NewValue
END
天哪这是一个巨大的触发器。我强烈建议你重新考虑一下这个问题——触发器可以在任何时候、多次触发,而你无法控制它被执行的时间和次数。因此,触发器应该灵活而精巧——最多只需要几行代码——但它不应该是这样一个怪物!这肯定会扼杀你的表现!谢谢你的建议。有没有方法不重复更新多个列的查询?谢谢您的回复,我会尝试一下。我遇到了一个与您提到的数据类型类似的问题。基本上,我只是将Col1改为FirstName varchar,将Col2改为LastName varchar,结果失败了。有什么建议吗?@milacay:我相信在提到这个问题之后,这个建议就在这里:您可能需要添加一些派生表来转换某些列。也就是说,不要从插入中选择,而是从选择中选择。。。CASTCol1为…,CASTCol2为。。。从“已插入”或类似的内容中取消插入。@T我,你能给我看一下交叉申请@Updated部分吗?谢谢
ALTER TRIGGER dbo.trg_MyTable_AuditLog
ON dbo.MyTable
FOR INSERT, UPDATE, DELETE
NOT FOR REPLICATION
AS
BEGIN
DECLARE @DATABASENAME SYSNAME = DB_NAME(),
@TABLENAME SYSNAME = N'MyTable',
@SCHEMANAME SYSNAME = N'dbo',
@INSERTED SMALLINT = 1,
@DELETED SMALLINT = 2,
@UPDATED SMALLINT = 3
DECLARE @action SMALLINT = 0
SELECT @action = CASE WHEN EXISTS(SELECT 1 FROM inserted) THEN @INSERTED ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM deleted) THEN @DELETED ELSE 0 END
IF @action = @INSERTED
BEGIN
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, ColumnName, Id, NULL, NewValue, 'INSERT'
FROM inserted
UNPIVOT (
NewValue
FOR ColumnName IN ( Col1, Col2 )
) upiv
END
IF @action = @DELETED
BEGIN
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, ColumnName, Id, OldValue, Null, 'DELETE'
FROM deleted
UNPIVOT (
OldValue
FOR ColumnName IN ( Col1, Col2 )
) upiv
END
IF @action = @UPDATED
BEGIN
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, upiv_inserted.ColumnName,
upiv_inserted.Id, upiv_deleted.OldValue, upiv_inserted.NewValue, 'UPDATE'
FROM (
SELECT ColumnName, Id, NewValue
FROM inserted
UNPIVOT (
NewValue
FOR ColumnName IN ( Col1, Col2 )
) upiv
) upiv_inserted
JOIN (
SELECT ColumnName, Id, OldValue
FROM deleted
UNPIVOT (
OldValue
FOR ColumnName IN ( Col1, Col2 )
) upiv
) upiv_deleted
ON upiv_deleted.Id = upiv_inserted.Id
AND upiv_deleted.ColumnName = upiv_inserted.ColumnName
WHERE upiv_deleted.OldValue <> upiv_inserted.NewValue
END
END
GO
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, ColumnName, Id, OldValue, Null, 'DELETE'
FROM deleted
CROSS APPLY (
VALUES
('Col1', Col1),
('Col2', Col2)
) upiv (ColumnName, OldValue)
IF @action = @UPDATED
BEGIN
INSERT INTO dbo.AuditLog (DatabaseName, SchemaName, TableName, ColumnName, KeyValue, OldValue, NewValue, TransactionType)
SELECT @DATABASENAME, @SCHEMANAME, @TABLENAME, upiv_inserted.ColumnName,
upiv_inserted.Id, upiv_deleted.OldValue, upiv_inserted.NewValue, 'UPDATE'
FROM (
SELECT ColumnName, Id, NewValue
FROM inserted
CROSS APPLY (
VALUES
('Col1', Col1),
('Col2', Col2)
) upiv (ColumnName, NewValue)
) upiv_inserted
JOIN (
SELECT ColumnName, Id, OldValue
FROM deleted
CROSS APPLY (
VALUES
('Col1', Col1),
('Col2', Col2)
) upiv (ColumnName, OldValue)
) upiv_deleted
ON upiv_deleted.Id = upiv_inserted.Id
AND upiv_deleted.ColumnName = upiv_inserted.ColumnName
WHERE upiv_deleted.OldValue <> upiv_inserted.NewValue
END