如何制作通用触发器来设置审计字段?
How to make a generic trigger to set the audit fields?
我想在我的 table 上自动设置审核字段 (UpdatedBy/UpdatedOn)。为此,我在每个 table 上都有一个触发器,如下所示:
CREATE TRIGGER [dbo].[tr_AsyncMessage_Upd] ON [dbo].[AsyncMessage] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE m
SET
m.UpdatedOn = CURRENT_TIMESTAMP
,m.UpdatedBy = SUSER_SNAME()
FROM dbo.AsyncMessage m
INNER JOIN inserted AS i
ON m.AsyncMessageID = i.AsyncMessageID
END
但是,我宁愿不必为每个 table 都编写触发器。有没有办法告诉 SQL 服务器为我自动设置它们?或者有没有办法让一个触发器覆盖所有 tables?
尝试这样的事情。复制此输出,并在 运行 之前检查它。这仅在 table 具有主键并且具有 updatedby 和 updatedon 列时有效。
SELECT 'CREATE TRIGGER tr_'+TABLE_NAME+'_Update ON '+TABLE_SCHEMA+'.'+TABLE_NAME+'
AFTER UPDATE
AS
BEGIN
UPDATE T SET UPDATEDBY=SYSTEM_USER, UPDATEDON=CURRENT_TIMESTAMP
FROM '+TABLE_SCHEMA+'.'+TABLE_NAME+' T
JOIN inserted I ON T.'+COLUMN_NAME+'=I.'+COLUMN_NAME+'
END'
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + CONSTRAINT_NAME), 'IsPrimaryKey') = 1
AND EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS C WHERE C.COLUMN_NAME='UpdatedOn' AND CU.TABLE_NAME=C.TABLE_NAME)
AND EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS C2 WHERE C2.COLUMN_NAME='UpdatedBy' AND CU.TABLE_NAME=C2.TABLE_NAME)
Sql 不是 C#,不要试图把它当作 C#。 C# 中的好的做法在 SQL 中不一定是好的做法。 SQL 是声明式的,通常同时修改多个 table 的能力有限。
只需为每个 table 写一次触发器,如果你这样做很多 tables,然后写一些为你写触发器的东西,然后 运行结果。
我想在我的 table 上自动设置审核字段 (UpdatedBy/UpdatedOn)。为此,我在每个 table 上都有一个触发器,如下所示:
CREATE TRIGGER [dbo].[tr_AsyncMessage_Upd] ON [dbo].[AsyncMessage] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE m
SET
m.UpdatedOn = CURRENT_TIMESTAMP
,m.UpdatedBy = SUSER_SNAME()
FROM dbo.AsyncMessage m
INNER JOIN inserted AS i
ON m.AsyncMessageID = i.AsyncMessageID
END
但是,我宁愿不必为每个 table 都编写触发器。有没有办法告诉 SQL 服务器为我自动设置它们?或者有没有办法让一个触发器覆盖所有 tables?
尝试这样的事情。复制此输出,并在 运行 之前检查它。这仅在 table 具有主键并且具有 updatedby 和 updatedon 列时有效。
SELECT 'CREATE TRIGGER tr_'+TABLE_NAME+'_Update ON '+TABLE_SCHEMA+'.'+TABLE_NAME+'
AFTER UPDATE
AS
BEGIN
UPDATE T SET UPDATEDBY=SYSTEM_USER, UPDATEDON=CURRENT_TIMESTAMP
FROM '+TABLE_SCHEMA+'.'+TABLE_NAME+' T
JOIN inserted I ON T.'+COLUMN_NAME+'=I.'+COLUMN_NAME+'
END'
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + CONSTRAINT_NAME), 'IsPrimaryKey') = 1
AND EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS C WHERE C.COLUMN_NAME='UpdatedOn' AND CU.TABLE_NAME=C.TABLE_NAME)
AND EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS C2 WHERE C2.COLUMN_NAME='UpdatedBy' AND CU.TABLE_NAME=C2.TABLE_NAME)
Sql 不是 C#,不要试图把它当作 C#。 C# 中的好的做法在 SQL 中不一定是好的做法。 SQL 是声明式的,通常同时修改多个 table 的能力有限。
只需为每个 table 写一次触发器,如果你这样做很多 tables,然后写一些为你写触发器的东西,然后 运行结果。