Проще всего просто создать три триггера - по одному для каждой операции:
CREATE TRIGGER trgUserInsert
ON dbo.User AFTER INSERT
AS BEGIN
INSERT INTO dbo.UserHistory............
END
CREATE TRIGGER trgUserDelete
ON dbo.User AFTER DELETE
AS BEGIN
INSERT INTO dbo.UserHistory............
END
CREATE TRIGGER trgUserUpdate
ON dbo.User AFTER UPDATE
AS BEGIN
INSERT INTO dbo.UserHistory............
END
Таким образом, все просто, и вы легко понимаете, что делаете, плюс это дает вам возможность отключить триггер для одной операции, если вы, например, Нужно вставить или удалить огромный список предметов.
Внутри триггера у вас есть две "псевдотаблицы" - Inserted
(для INSERT и UPDATE) и Deleted
(для UPDATE и DELETE). Эти псевдотаблицы содержат значения для вновь вставленных значений (или обновленных значений в UPDATE), или тех, которые были удалены (для DELETE) или были обновлены (старые значения до обновления для операции UPDATE).
Вы должны знать, что триггер будет вызываться один раз, даже если вы обновите огромное количество строк, например, Inserted
и Deleted
обычно содержат несколько строк.
В качестве примера вы могли бы написать триггер «ПОСЛЕ ВСТАВКИ», как этот (просто угадав, какой может быть структура вашей таблицы ....):
CREATE TRIGGER trgUserInsert
ON dbo.User AFTER INSERT
AS BEGIN
INSERT INTO
dbo.UserHistory(UserID, Action, DateTimeStamp, AuditMessage)
SELECT
i.UserID, 'INSERT', getdate(), 'User inserted into table'
FROM
Inserted i
END
Вы ищете способ узнать, какое "действие" вызвало этот триггер? Я не вижу никакого способа сделать это - еще одна причина держать три триггера отдельно. Единственный способ выяснить это - подсчитать строки в таблицах Inserted
и Updated
:
- если оба значения больше нуля, это
UPDATE
- если в таблице
Inserted
есть строки, а в Deleted
нет, то это INSERT
- если в таблице
Inserted
нет строк, а в Deleted
- DELETE
Вы также ищете «список полей, которые были обновлены» - опять же, у вас просто не будет простого решения. Вы можете просто просмотреть интересующие вас поля в таблице «Пользователи» и проверить
IF UPDATE(fieldname) ......
но это становится немного утомительным.
Или вы можете использовать функцию COLUMNS_UPDATED()
- это, однако, не дает вам хороший список имен столбцов, но VARBINARY, в котором каждый столбец в основном один бит, и если он включен , этот столбец был обновлен. Не очень прост в использовании .....
Если вы действительно хотите создать один большой триггер, это может послужить основой - он определяет, какая операция вызвала срабатывание триггера, и вставит записи в вашу таблицу User_History:
CREATE TRIGGER trgUser_Universal
ON dbo.Users
AFTER INSERT, UPDATE, DELETE
AS BEGIN
DECLARE @InsHasRows BIT = 0
DECLARE @DelHasRows BIT = 0
IF EXISTS(SELECT TOP 1 * FROM INSERTED)
SET @InsHasRows = 1
IF EXISTS(SELECT TOP 1 * FROM DELETED)
SET @DelHasRows = 1
DECLARE @TriggerAction VARCHAR(20)
IF @InsHasRows = 1 AND @DelHasRows = 1
SET @TriggerAction = 'UPDATE'
ELSE
IF @InsHasRows = 1
SET @TriggerAction = 'INSERT'
ELSE
SET @TriggerAction = 'DELETE'
IF @InsHasRows = 1
INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)
SELECT i.UserId, @TriggerAction, null, getdate()
FROM INSERTED i
ELSE
INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)
SELECT d.UserId, @TriggerAction, null, getdate()
FROM DELETED d
END
Я пока не включил выяснение того, какие поля были обновлены, - это оставлено читателю в качестве упражнения: -)
Помогает ли это вообще?