我有一个用户表,其中包含| Firstname | Surname | DateOfBirth | ......以及其他一些专栏。在该特定表上,我有一个更新触发器,如果有人更改任何用户值,则会创建审核。
我的问题是,管理层希望以下列方式显示视觉审核:
DateChanged |Change |Details
--------------------------------------------------------------------------------
2010/01/01 |FirstName Changed |FirstName Changed from "John" to "Joe"
2010/01/01 |FirstName And Lastname Changed|FirstName Changed from "Smith" to "White "And Lastname changed from "els" to "brown"
2010/01/01 |User Deleted |"ark Anrdrews" was deleted
我相信解决这个问题的最佳方法是修改存储过程,但是如何指示触发器记录这些事情呢?
答案 0 :(得分:5)
您可以在名为COLUMS_UPDATED()的触发器中调用一个函数。这将返回触发器表中列的位图,其中1表示表中的相应列已被修改。它本身就不那么精彩,因为你最终会得到一个列索引列表,并且仍然需要编写一个CASE语句来确定哪些列被修改。如果你没有很多列可能不那么糟糕,但如果你想要更通用的东西,你可以加入information_schema.columns将这些列索引转换为列名
这是一个小样本,展示你可以做的事情:
CREATE TABLE test (
ID Int NOT null IDENTITY(1,1),
NAME VARCHAR(50),
Age INT
)
GO
---------------------------------------
CREATE TRIGGER tr_test ON test FOR UPDATE
AS
DECLARE @cols varbinary= COLUMNS_UPDATED()
DECLARE @altered TABLE(colid int)
DECLARE @index int=1
WHILE @cols>0 BEGIN
IF @cols & 1 <> 0 INSERT @altered(colid) VALUES(@index)
SET @index=@index+1
SET @cols=@cols/2
END
DECLARE @text varchar(MAX)=''
SELECT @text=@text+C.COLUMN_NAME+', '
FROM information_schema.COLUMNS C JOIN @altered A ON c.ordinal_position=A.colid
WHERE table_name='test'
PRINT @text
GO
------------------------------------------------------
INSERT test(NAME, age) VALUES('test',12)
UPDATE test SET age=15
UPDATE test SET NAME='fred'
UPDATE test SET age=18,NAME='bert'
DROP TABLE test
答案 1 :(得分:1)
MS SQL Server具有UPDATED()函数。它允许您指定字段名称以告知是否有任何记录已更改该字段。
然而,我的经验是,所需的功能性通常超过这种通用功能的限制。我通常最终只是简单地将INSERTED伪表连接到DELETED伪表并自己进行比较。*这样的比较假定表具有唯一标识,无论是单个字段还是某个字段的复合键。