我对数据库表有一个审计触发器,这是从在线文章中获得的。触发器效果很好,但是我想根据需要自定义它。我被困在一个地方,需要帮助。我对此并不陌生,所以这可能是一个简单的问题。
ALTER TRIGGER [d2c].[tr_referral_client] ON [d2c].[referral_client] FOR
UPDATE, DELETE, Insert
AS
SET NOCOUNT ON
DECLARE @bit INT ,
@field INT ,
@fieldId INT ,
@maxfield INT ,
@char INT ,
@fieldname VARCHAR(128) ,
@FieldDisplayName VARCHAR(128),
@TableDisplayName VARCHAR(128),
@SchemaName VARCHAR(128) ,
@TableName VARCHAR(128) ,
@PKCols VARCHAR(1000) ,
@sql VARCHAR(2000),
@UpdateDate VARCHAR(21) ,
@UserName VARCHAR(128) ,
@Type CHAR(1) ,
@PKSelect VARCHAR(1000) ,
@linkageID VARCHAR(1000) ,
@FullTableName VARCHAR(256),
@oldvalue VARCHAR(1000),
@newvalue VARCHAR(1000),
@modified_by VARCHAR(20)='modified_by',
@isviewable char(1)
--You will need to change @TableName to match the table to be audited
SELECT @TableName = 'referral_client', @SchemaName = 'd2c'
SELECT @FullTableName = @SchemaName + '.' + @TableName
-- date and user
SELECT @UserName = SYSTEM_USER ,
@UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112)
+ ' ' + CONVERT(VARCHAR(12), GETDATE(), 114)
-- Action
IF EXISTS (SELECT * FROM inserted)
IF EXISTS (SELECT * FROM deleted)
SELECT @Type = 'U'
ELSE
SELECT @Type = 'I'
ELSE
SELECT @Type = 'D'
-- get list of columns
SELECT * INTO #ins FROM inserted
SELECT * INTO #del FROM deleted
if @type in('U','D')
select @isviewable = '1'
else
select @isviewable = '0'
-- Get primary key columns for full outer join
SELECT @PKCols = COALESCE(@PKCols + ' and', ' on')
+ ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = @TableName
AND pk.TABLE_SCHEMA = @SchemaName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
AND c.CONSTRAINT_SCHEMA = pk.TABLE_SCHEMA
-- Get primary key select for insert
SELECT @PKSelect = COALESCE(@PKSelect+'+','') + '''' +
'''+convert(varchar(100),coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+'''''
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = @TableName
AND pk.TABLE_SCHEMA = @SchemaName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
AND c.CONSTRAINT_SCHEMA = pk.TABLE_SCHEMA
-- Get client id select for insert
SELECT @linkageID = COALESCE(@linkageID+'+','') + '''' +
'''+convert(varchar(100),coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+'''''
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE c.TABLE_NAME = @TableName
AND c.TABLE_SCHEMA = @SchemaName
AND c.COLUMN_NAME = 'linkage_profile_id'
IF @PKCols IS NULL
BEGIN
RAISERROR('no PK on table %s', 16, -1, @FullTableName)
RETURN
END
---------------------Display value for table
SET @TableDisplayName = CASE @TableName
WHEN 'referral_client' THEN 'Referrals'
END
--------------------------
SELECT @field = 0,
@maxfield = MAX(ORDINAL_POSITION)
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = @SchemaName
WHILE @field < @maxfield
BEGIN
SELECT @fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @TableName
AND TABLE_SCHEMA = @SchemaName
AND ORDINAL_POSITION = @field
SELECT @fieldid = COLUMNPROPERTY(OBJECT_ID(@FullTableName), @fieldname, 'ColumnID')
SELECT @field = MIN(ORDINAL_POSITION)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @TableName
AND TABLE_SCHEMA = @SchemaName
AND ORDINAL_POSITION > @field
select @bit = (@fieldid - 1 )% 8 + 1
select @bit = power(2,@bit - 1)
select @char = ((@fieldid - 1) / 8) + 1
--------------------getting referral values
if @fieldname in ('referral_id')
begin
select @oldvalue = c.referral_name
from lu.referral c inner join deleted d
on d.referral_id = c.referral_id
select @newvalue = c.referral_name
from lu.referral c inner join inserted i
on i.referral_id = c.referral_id
end
-------------------------
if @fieldname NOT in ('referral_id')
begin
select @oldvalue ='Code here'====================================>>
--convert(varchar(1000),d.' + @fieldname + ')'+ ',
Select @newvalue = 'Code here'==================================>>
--convert(varchar(1000),i.' + @fieldname + ')'+ ',
END
------------------
if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in ('I','D')
if @fieldname not in ('modified_by','date_modified')
--------------display values for fields
SET @FieldDisplayName = CASE @fieldname
WHEN 'referral_client_id' THEN 'Referral ID'
WHEN 'linkage_profile_id' THEN 'Linkage Profile ID'
WHEN 'referral_id' THEN 'Referral Name'
WHEN 'other_desc' THEN 'Other Description'
WHEN 'Created_by' THEN 'Record Created By'
WHEN 'Date_created' THEN 'Record Creation Date'
WHEN 'Modified_by' THEN 'Record Last Modified By'
WHEN 'date_modified' THEN 'Record Last Modified Date'
END
---------------------------
BEGIN
SELECT @sql = '
insert d2c.Audit ( Type,
TableSchema,
TableName,
tabledisplayname,
fielddisplayname,
PK,
linkage_profile_id,
is_viewable,
FieldName,
OldValue,
NewValue,
UpdateDate,
UserName,
Application
)
select ''' + @Type + ''',
''' + @SchemaName + ''',
''' + @TableName + ''',
''' + @TableDisplayName + ''',
''' + @FieldDisplayName + ''',
' + @PKSelect+ ',
' + @linkageID+ ',
'+ @isviewable+' ,
''' + @fieldname + ''''+ ',' + @oldvalue + ',
' + @newvalue + ',
''' + @UpdateDate + ''''+ ',
''' + @UserName + '''' + ',
''' + REPLACE(APP_NAME(), '''', '''''') + ''''
+ ' from #ins i full outer join #del d'
+ @PKCols
+ ' where i.' + @fieldname + ' <> d.' + @fieldname
+ ' or (i.' + @fieldname + ' is null and d.' + @fieldname + ' is not null)'
+ ' or (i.' + @fieldname + ' is not null and d.' + @fieldname + ' is null)'
EXEC (@sql)
END
END
这是我正在使用的触发器。在插入时,使用以下代码插入了更改后的值在审计表中,旧值和新值:-convert(varchar(1000),d.' + @fieldname + ')'+ ',
用于删除,--convert(varchar(1000),i.' + @fieldname + ')'+ ',
用于插入。
由于我需要修改特定列的值,因此添加了if语句,并使用@oldvalue
和@newvalue
生成所需的内容,然后将其传递给insert语句。
对于一次性列,我获得了正确的值,但是对于其余列,当我尝试使用上述代码时,我将相同的字符串插入到审计表中。请帮忙!
我可以回答您可能遇到的任何问题。