Я боролся с этим в течение нескольких дней. У меня есть табличный триггер, который создает запись аудита для каждого действия «Вставить», «Обновить» или «Удалить» и помещает ее в соответствующую таблицу аудита в соседней базе данных. Эта новая запись аудита содержит значение первичного ключа исходных таблиц, тип действия, моментальный снимок записи в формате XML, текущую дату и текущего пользователя.
Каждая из перечисленных выше порций информации присваивается\вычисляется из таблиц INSERTED\DELETED и присваивается значениям параметров, которые затем передаются в хранимую процедуру, выполняющую динамическую SQL-процедуру для ВСТАВКИ новой записи. Ради этого вопроса динамический SQL представляет собой простой оператор INSERT (показан ниже):
INSERT INTO [340bAudit].[aud].[TableName]
(
RecordID
,ActionType
,xml_snapshot
,ModifiedDate
,ModifiedBy
)
VALUES (@RecordPK
,@action
,@data
,GETDATE()
,SYSTEM_USER
)
Этот триггер работает нормально, пока обновляется только запись, но как только возникает ситуация, когда несколько записей обновляются в одном выражении, я получаю следующее:
Подзапрос вернул более 1 значения. Это не разрешено, когда подзапрос следует за =, !=, ‹, ‹= , >, >= или когда подзапрос используется как выражение. Заявление было прекращено.
Триггер выглядит так:
ALTER TRIGGER [dbo].[RollOver_onUpdate] ON [dbo].[RollOver]
AFTER INSERT, update, DELETE
FOR EACH ROW
AS
BEGIN
/******** Audit *******/
DECLARE @TableName varchar(50)
,@RecordPK varchar(10)
,@action char(1)
,@data xml
SET @TableName = 'RollOver'
SET @RecordPK = (SELECT DISTINCT RollOverID FROM INSERTED)
SET @action = 'I'; -- Set Action to Insert by default.
IF EXISTS (SELECT * FROM DELETED)
BEGIN
SET @action =
CASE
WHEN EXISTS (SELECT * FROM INSERTED)
THEN 'U' -- Set Action to Updated.
ELSE 'D' -- Set Action to Deleted.
END
END
SET @data = CASE WHEN @action <> 'D' THEN (SELECT'<rows>' + (SELECT * FROM INSERTED i FOR xml PATH) + '</rows>')
ELSE (SELECT'<rows>' + (SELECT * FROM DELETED d FOR xml PATH) + '</rows>')
END
--Execute Audit Record Creation
EXECUTE sp_CreateAuditRecord @Table = @TableName
,@RecordID = @RecordPK
,@ActionType = @action
,@XML = @data
END
Могу ли я изменить этот триггер, чтобы он выполнялся построчно в этом случае? А если нет, то куда мне идти отсюда?
Я бы очень хотел сохранить гибкость динамического SQL, так как каждая таблица в моей базе данных использует одну и ту же логику аудита, и это первая и единственная таблица, которая, по-видимому, имеет проблему, которая, как я полагаю, связана с «использованием». ' этой таблицы.