基于程序的审计触发器 table
Procedure based trigger for audit table
我有 2 个 table,一个主 table 和一个审计 table。
create sequence dbo.users_seq;
create table dbo.users
(
id bigint primary key default(next value for dbo.users_seq),
user_data nvarchar(max) not null check(isjson(user_data) = 1),
timestamp datetime2 not null default sysdatetime(),
updated_timestamp datetime2 not null default sysdatetime()
);
create sequence dbo.users_audit_seq;
create table dbo.users_audit
(
id bigint primary key default(next value for dbo.users_audit_seq),
users_id bigint not null, --id from `users` table
old nvarchar(max) not null check(isjson(old) = 1), --original row from `users` table
new nvarchar(max) not null check(isjson(new) = 1), --new row from `users` table
updated_by varchar(100) not null, --username info
timestamp datetime2 not null default sysdatetime()
);
我希望在 users
主 table 上创建一个 for update
触发器,它调用一个通用过程,该过程可用于具有类似审计的其他 tables table 架构。
通用程序应写入其审计 table(users
table 应写入 users_audit
table 但同样的程序也适用于users2
table 并写入 users2_audit
table).
注意:临时 tables 方法不起作用
我会先说临时表或 SQL 审计对于这种事情要好得多,你基本上是在重新发明轮子。
尽管如此,下面应该为您提供了一个很好的触发器模型
CREATE OR ALTER TRIGGER TR_users ON users
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON; -- prevent issues with bad client drivers
IF NOT EXISTS (SELECT 1 FROM inserted) AND NOT EXISTS (SELECT 1 FROM deleted)
RETURN; -- early bail-out
INSERT users_audit (users_id, old, new, updated_by)
SELECT
ISNULL(i.id, d.id),
i.user_data,
d.user_data,
SUSER_SNAME()
FROM inserted i
FULL JOIN deleted d ON d.id = i.id -- full join to match by all primary key columns
WHERE NOT EXISTS (
SELECT i.user_data -- add other columns here
INTERSECT -- because INTERSECT deals correctly with nulls
SELECT d.user_data
);
go
如果您想要为每个 table 使用此代码,我强烈建议您不要尝试编写单个动态触发器,而是编写一个可以生成特定触发器和审核 tables 的工具每个 table。请注意,主键可能包含多个列,您需要匹配所有这些列。
我有 2 个 table,一个主 table 和一个审计 table。
create sequence dbo.users_seq;
create table dbo.users
(
id bigint primary key default(next value for dbo.users_seq),
user_data nvarchar(max) not null check(isjson(user_data) = 1),
timestamp datetime2 not null default sysdatetime(),
updated_timestamp datetime2 not null default sysdatetime()
);
create sequence dbo.users_audit_seq;
create table dbo.users_audit
(
id bigint primary key default(next value for dbo.users_audit_seq),
users_id bigint not null, --id from `users` table
old nvarchar(max) not null check(isjson(old) = 1), --original row from `users` table
new nvarchar(max) not null check(isjson(new) = 1), --new row from `users` table
updated_by varchar(100) not null, --username info
timestamp datetime2 not null default sysdatetime()
);
我希望在 users
主 table 上创建一个 for update
触发器,它调用一个通用过程,该过程可用于具有类似审计的其他 tables table 架构。
通用程序应写入其审计 table(users
table 应写入 users_audit
table 但同样的程序也适用于users2
table 并写入 users2_audit
table).
注意:临时 tables 方法不起作用
我会先说临时表或 SQL 审计对于这种事情要好得多,你基本上是在重新发明轮子。
尽管如此,下面应该为您提供了一个很好的触发器模型
CREATE OR ALTER TRIGGER TR_users ON users
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON; -- prevent issues with bad client drivers
IF NOT EXISTS (SELECT 1 FROM inserted) AND NOT EXISTS (SELECT 1 FROM deleted)
RETURN; -- early bail-out
INSERT users_audit (users_id, old, new, updated_by)
SELECT
ISNULL(i.id, d.id),
i.user_data,
d.user_data,
SUSER_SNAME()
FROM inserted i
FULL JOIN deleted d ON d.id = i.id -- full join to match by all primary key columns
WHERE NOT EXISTS (
SELECT i.user_data -- add other columns here
INTERSECT -- because INTERSECT deals correctly with nulls
SELECT d.user_data
);
go
如果您想要为每个 table 使用此代码,我强烈建议您不要尝试编写单个动态触发器,而是编写一个可以生成特定触发器和审核 tables 的工具每个 table。请注意,主键可能包含多个列,您需要匹配所有这些列。