外键的审计触发器
Posted
技术标签:
【中文标题】外键的审计触发器【英文标题】:Audit trigger for foreign key 【发布时间】:2020-12-05 01:57:18 【问题描述】:下面的代码是我的Branch
表的审核触发器。它能够记录Branch
表中的任何编辑或插入更改。
但是,我有一个指向 BranchZone
表的外键 BranchZoneID
。我想这样做,以便记录对此外键的任何更改,并且它将显示BranchZone
表中的BranchZoneName
而不是BranchZoneID
。
我尝试使用代码为外键属性BranchZoneID
创建触发器。但是,我无法为其创建工作触发器。
BranchZoneID
的触发器不起作用。我需要改变什么?
create trigger Branch_Audit
on dbo.Branch
after insert, update
not for replication
as
begin
set nocount on;
declare @operation char(10) = case when exists (select * from deleted) then 'Edit' else 'Insert' end;
insert AuditLog
(TableName, ModifiedBy, AuditDateTime, AuditAction, ID, ChangedColumn, OldValue, NewValue)
select
'Branch', suser_sname(), getdate(), @operation, I.BranchZoneID,
'BranchName', convert(varchar(21),D.BranchName), convert(varchar(21),I.BranchName)
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
where coalesce(I.BranchName,'') <> coalesce(D.BranchName,'')
and update(BranchName)
union all
select
'Branch', suser_sname(), getdate(), @operation, I.BranchID,
'BranchAddress', D.BranchAddress, I.BranchAddress
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
where coalesce(I.BranchAddress,'') <> coalesce(D.BranchAddress,'')
and update(BranchAddress)
union all
select
'Branch', suser_sname(), getdate(), @operation, I.BranchID,
'BranchGeoLocationLat', D.BranchGeoLocationLat, I.BranchGeoLocationLat
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
where coalesce(I.BranchGeoLocationLat,'') <> coalesce(D.BranchGeoLocationLat,'')
and update(BranchGeoLocationLat)
union all
select
'Branch', suser_sname(), getdate(), @operation, I.BranchID,
'BranchGeoLocationLong', D.BranchGeoLocationLong, I.BranchGeoLocationLong
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
where coalesce(I.BranchGeoLocationLong,'') <> coalesce(D.BranchGeoLocationLong,'')
and update(BranchGeoLocationLong)
union all
select
'Branch', SUSER_SNAME(), GETDATE(), @operation, I.BranchID,
'BranchZoneID', OWD.BranchZoneName, NWD.BranchZoneName
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
where coalesce(I.BranchZoneID,'') <> coalesce(D.BranchZoneID,'')
and update(BranchZoneID)
-- Fetch Branch Zone Name
on deleted.BranchZoneID = OWD.BranchZoneID
join dbo.BranchZone NWD
on inserted.BranchZoneID = NWD.BranchZoneID
end;
【问题讨论】:
那么有什么大不了的?您加入适当的表。您不能做的只是简单地“发明”一个别名并在您的 select 语句中引用它。并且为了将来参考,当您的问题包含错误时,您应该发布完整和实际的错误消息。而且您实际上应该提到您的代码会产生错误 - 这是因为 OWD 和 NWD 是尚未定义的别名。 【参考方案1】:您只是对您的加入感到困惑......正确加入并且它按预期工作。请记住,当使用表别名时,从那时起您只能使用别名引用表,例如I
而不是 Inserted
。
还假设BranchZoneID
是int
,您需要将coalesce
设置为未使用的int
,例如0
不是空字符串。
select
'Branch', suser_sname(), getdate(), @operation, I.BranchID
, 'BranchZoneID', OWD.BranchZoneName, NWD.BranchZoneName
from inserted I
left outer join deleted D on I.BranchID = D.BranchID
-- Fetch Branch Zone Names
left join dbo.BranchZone OWD on OWD.BranchZoneID = D.BranchZoneID
left join dbo.BranchZone NWD on NWD.BranchZoneID = I.BranchZoneID
where coalesce(I.BranchZoneID,0) <> coalesce(D.BranchZoneID,0)
and update(BranchZoneID);
如果BranchZoneID
是uniqueidentifer
,您将使用:
where coalesce(I.BranchZoneID,'00000000-0000-0000-0000-000000000000') <> coalesce(D.BranchZoneID,'00000000-0000-0000-0000-000000000000')
当使用coalesce
以这种方式比较值时,您需要选择一个对数据类型有效但在您的数据中无效的值。
【讨论】:
您好,如果 BranchZoneID 是唯一标识符,我必须将 (I.BranchZoneID,0) 中的“0”更改为什么? 当我尝试在我的网站中编辑 BranchZoneID 时,弹出此错误:“SqlException: Error convert data type nvarchar to numeric.” 'OldValue' 和 'NewValue' 的数据类型是 Nvarchar(250)。但是,我怀疑是否需要更改其数据类型。 如果BranchZoneID
是唯一标识符,我不知道会发生什么。在某处您有一个 int
列,但您没有正确转换 - 但没有看到您的表定义和示例数据,我无法提供任何建议。
我的表中没有 int 列。以上是关于外键的审计触发器的主要内容,如果未能解决你的问题,请参考以下文章