TSQL 更新触发器,将所有已更新的值插入到日志表中

问题描述 投票:0回答:1

我有一个触发器,仅在管理器更新时记录。我需要更改它,以便它为每个更新的字段插入一条记录。

例如此语句将在表 test_UpdateLog 中插入 3 条记录: 更新测试集经理='A',位置='B',部门='D';

更改触发器 [dbo].[TR_test_UpdateLog]

ON [dbo]。[测试]

更新后

AS

开始

INSERT INTO dbo.test_UpdateLog(TableName,PrimaryKeyValue,ColumnName,OldValue,NewValue,UpdatedBy)

  SELECT 'test',i.Email,'Manager', d.Manager, i.Manager,USER_NAME()

  FROM Inserted i

  INNER JOIN Deleted d ON i.Email = d.Email

  WHERE d.Manager <> i.Manager

结束;

sql t-sql
1个回答
0
投票

一种方法就是一直存储所有更改......这在我的经验中非常典型。

然后,您可以查询您感兴趣的特定更改 - 请参阅本示例中的最后一个查询,其中我仅查询管理器中的更改。

CREATE TABLE dbo.Manager (
    Id INT,
    Email VARCHAR(50),
    Manager VARCHAR(50),
    [Location] VARCHAR(50),
    PRIMARY KEY (Id))

CREATE TABLE dbo.Audit_Manager (
    AuditAction CHAR(1),
    AuditActionDateTime DATETIME,
    AuditActionBy VARCHAR(50),
    Id INT,
    Email VARCHAR(50),
    Manager VARCHAR(50),
    [Location] VARCHAR(50))
GO

CREATE OR ALTER TRIGGER Manager_AfterUpdate ON dbo.Manager
FOR UPDATE 
AS
BEGIN
    INSERT INTO dbo.Audit_Manager (
        AuditAction,
        AuditActionDateTime,
        AuditActionBy, Id,
        Email,
        Manager,
        [Location])
    SELECT 
        'I',
        GETDATE(),
        USER_NAME(),
        Deleted.Id,
        Deleted.Email,
        Deleted.Manager,
        Deleted.[Location]
    FROM 
        Deleted
END
GO

CREATE OR ALTER TRIGGER Manager_AfterDelete ON dbo.Manager
FOR DELETE
AS
BEGIN
    INSERT INTO dbo.Audit_Manager (
        AuditAction,
        AuditActionDateTime,
        AuditActionBy,
        Id,
        Email,
        Manager,
        [Location])
    SELECT 
        'D',
        GETDATE(),
        USER_NAME(),
        Deleted.Id,
        Deleted.Email,
        Deleted.Manager,
        Deleted.[Location]
    FROM 
        Deleted
END
GO

-- Test Runner
INSERT INTO dbo.Manager (Id, Email, Manager, [Location])
VALUES 
    (1, '[email protected]', 'John', 'X'),
    (2, '[email protected]', 'Paul', 'X')
WAITFOR DELAY '00:00:01'
UPDATE dbo.Manager SET Email = '[email protected]' WHERE Id = 1
WAITFOR DELAY '00:00:01'
UPDATE dbo.Manager SET Email = '[email protected]' WHERE Id = 1
WAITFOR DELAY '00:00:01'
UPDATE dbo.Manager SET Manager = 'Mary' WHERE Id = 1
WAITFOR DELAY '00:00:01'
UPDATE dbo.Manager SET [Location] = 'Y' WHERE Id = 1
WAITFOR DELAY '00:00:01'
UPDATE dbo.Manager SET Manager = 'Jane' WHERE Id = 1

-- ---------------------------------------------------
-- View changes (each row is compared to the next row)
-- ---------------------------------------------------
;WITH delta AS (
SELECT 
    AuditAction,
    AuditActionDateTime, 
    AuditActionBy,
    Id,
    Email,
    Manager,
    [Location]
FROM dbo.Audit_Manager m
UNION ALL
SELECT 
    NULL AS AuditAction,
    NULL AS AuditActionDateTime, 
    NULL AS AuditActionBy,
    Id,
    Email,
    Manager,
    [Location]
FROM dbo.Manager m
)
SELECT * 
FROM delta 
ORDER BY 
    Id, 
    IIF(AuditActionDateTime IS NULL, 0, 1),
    AuditActionDateTime DESC

-- --------------------------------------------
-- View a particular change (change of manager)
-- --------------------------------------------
;WITH delta AS (
    SELECT 
        AuditAction,
        AuditActionDateTime, 
        AuditActionBy,
        Id,
        Email,
        Manager,
        [Location]
    FROM dbo.Audit_Manager m
    UNION ALL
    SELECT 
        NULL AS AuditAction,
        NULL AS AuditActionDateTime, 
        NULL AS AuditActionBy,
        Id,
        Email,
        Manager,
        [Location]
    FROM dbo.Manager m
),
delta_ordered AS (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY Id ORDER BY AuditActionDateTime DESC) AS RN
    FROM delta
)
SELECT t1.AuditAction, t1.AuditActionDateTime, t1.AuditActionBy, t1.Id, t1.Manager AS Manager_Was, t2.Manager AS Manager_Is
FROM delta_ordered t1
INNER JOIN delta_ordered t2
ON t1.Id = t2.Id
AND t1.RN = t2.RN-1
AND t1.Manager <> t2.Manager
ORDER BY 
    t1.Id,
    t1.RN
© www.soinside.com 2019 - 2024. All rights reserved.