gpt4 book ai didi

sql - 如何创建通用 SQL Server 存储过程以根据触发器中的插入和删除执行插入到审计表中

转载 作者:行者123 更新时间:2023-12-04 16:48:02 24 4
gpt4 key购买 nike

我已经根据以下帖子的第一个答案提供的信息实现了一个审计跟踪框架:

SQL Server history table - populate through SP or Trigger?

最终,我实现的框架对每个表使用三个触发器,它们根据对表的更改插入审计信息。

我的插入和删除审计触发器相当简单。但是,更新触发器要复杂得多,因为触发器必须检查以确定每列是否受审计控制,然后根据 Inserted 和 Deleted 列中的列值是否相等来执行插入我不想写不必要的审计记录。最后,我想知道是否有一种方法可以编写一个存储过程,通过允许我动态执行下面的插入语句来减少触发器中的代码量。基本上,我设想触发器使用受审计控制的每个列名触发 sproc,然后存储过程将使用列名来执行下面的代码片段。目前,我在审计控制下的每一列都有以下代码,不幸的是,这会导致大量冗余代码。

建议更改后的修订触发器

CREATE TRIGGER [dbo].[Audit_Customers_Update] ON [dbo].[Customers]
FOR UPDATE AS

select FirstName,LastName into #deleted from deleted;

declare /*const*/ @TABLE_NAME sysname = '[table name]';

declare f cursor
local
forward_only
read_only
for
select c.name, quotename(c.name, '[')
from
sys.columns c
inner join sys.types t on c.system_type_id = t.system_type_id
where
c.object_id = object_id(@TABLE_NAME)
and c.is_computed = 0
and c.is_identity = 0
and t.name not in ('text', 'image', 'timestamp', 'xml')
and (substring(COLUMNS_UPDATED(), ((c.column_id - 1) / 8) + 1, 1) & power(2, (c.column_id - 1) % 8)) > 0
;

declare @field_name sysname, @field_name_sanitised sysname;
create table #results (row_id int not null,
field_name sysname not null,
oldval nvarchar(150) null,
newval nvarchar(150) null);

-- For each changed field, insert what exactly changed into #results

open f;

fetch next from f into @field_name, @field_name_sanitised;
while @@fetch_status = 0
begin
declare @query nvarchar(4000);

set @query = N'insert into #results(row_id, field_name, oldval, newval)
select d.row_id, @field_name, d.' + @field_name_sanitised + N', i.' + @field_name_sanitised + N'
from
#deleted d inner join ' + @TABLE_NAME + N' i on d.row_id = i.row_id
where
(d.' + @field_name_sanitised + N' <> i.' + @field_name_sanitised + N')
or
(case when d.' + @field_name_sanitised + N' is null then 1 else 0 end <> case when i.' + @field_name_sanitised + N' is null then 1 else 0 end);'
;

exec sp_executesql
@stmt = @query,
@params = N'@field_name sysname',
@field_name = @field_name
;

fetch next from f into @field_name, @field_name_sanitised;
end;

close f;
deallocate f;

-- Do something meaningful to #results here

我如何访问#results?我必须使用游标吗?

最佳答案

我们已经通过以下方式解决了这个问题。

select <list of tracked columns here> into #deleted from deleted;

declare /*const*/ @TABLE_NAME sysname = '[table name]';

declare f cursor
local
forward_only
read_only
for
select c.name, quotename(c.name, '[')
from
sys.columns c
inner join sys.types t on c.system_type_id = t.system_type_id
where
c.object_id = object_id(@TABLE_NAME)
and c.is_computed = 0
and c.is_identity = 0
and t.name not in ('text', 'image', 'timestamp', 'xml')
and (substring(COLUMNS_UPDATED(), ((c.column_id - 1) / 8) + 1, 1) & power(2, (c.column_id - 1) % 8)) > 0
;

declare @field_name sysname, @field_name_sanitised sysname;
create table #results (row_id int not null, field_name sysname not null, oldval nvarchar(150) null, newval nvarchar(150) null);

-- For each changed field, insert what exactly changed into #results

open f;

fetch next from f into @field_name, @field_name_sanitised;
while @@fetch_status = 0
begin
declare @query nvarchar(4000);

set @query = N'insert into #results(row_id, field_name, oldval, newval)
select d.row_id, @field_name, d.' + @field_name_sanitised + N', i.' + @field_name_sanitised + N'
from
#deleted d inner join ' + @TABLE_NAME + N' i on d.row_id = i.row_id
where
(d.' + @field_name_sanitised + N' <> i.' + @field_name_sanitised + N')
or
(case when d.' + @field_name_sanitised + N' is null then 1 else 0 end <> case when i.' + @field_name_sanitised + N' is null then 1 else 0 end);'
;

exec sp_executesql
@stmt = @query,
@params = N'@field_name sysname',
@field_name = @field_name
;

fetch next from f into @field_name, @field_name_sanitised;
end;

close f;
deallocate f;

-- Do something meaningful to #results here

相关阅读:
  • COLUMNS_UPDATED
  • sys.columns
  • 关于sql - 如何创建通用 SQL Server 存储过程以根据触发器中的插入和删除执行插入到审计表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8873335/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com