#sql-server #tsql #triggers #audit
#sql-сервер #tsql #триггеры #аудит
Вопрос:
Приведенный ниже код является триггером аудита для моей Branch
таблицы. Он способен записывать любые изменения редактирования или вставки из Branch
таблицы.
Однако у меня есть внешний ключ BranchZoneID
к BranchZone
таблице. Я хочу сделать так, чтобы любые изменения в этом внешнем ключе записывались, и чтобы он отображал BranchZoneName
из BranchZone
таблицы вместо 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;
Комментарии:
1. Так в чем же проблема? Вы присоединяетесь к соответствующей таблице. Чего вы не можете сделать, так это просто «изобрести» псевдоним и ссылаться на него в своем операторе select. И для дальнейшего использования, когда ваша проблема включает ошибки, вы должны публиковать полные и фактические сообщения об ошибках. И вам действительно следует упомянуть, что ваш код генерирует ошибки, что и происходит, поскольку OWD и NWD являются псевдонимами, которые не были определены.
Ответ №1:
Вы просто перепутали со своим join… присоединяйтесь правильно, и это работает так, как задумано. И помните, что при использовании псевдонима таблицы с этого момента вы можете ссылаться на таблицу только с использованием псевдонима, например, 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
для сравнения значений таким образом вам необходимо выбрать значение, которое допустимо для типа данных, но которое недопустимо в ваших данных.
Комментарии:
1. Привет, если BranchZoneID является уникальным идентификатором, на что мне нужно изменить ‘0’ в (I.BranchZoneID, 0)?
2. Когда я пытаюсь отредактировать BranchZoneID на моем веб-сайте, появляется эта ошибка: «SQLException: ошибка преобразования типа данных nvarchar в числовой».
3. Типом данных ‘oldValue’ и ‘newValue’ является Nvarchar(250). Однако я сомневаюсь, что мне нужно менять его тип данных.
4. Я не вижу, как это могло бы произойти, если
BranchZoneID
это uniqueidentifier. Где-то у вас естьint
столбец, который вы неправильно конвертируете, но, не видя ваших определений таблиц и образцов данных, я не могу предложить никаких предложений.5. В моей таблице нет столбца int.