【问题标题】:How can I structure a trigger to record previous values when updated?如何构建触发器以在更新时记录以前的值?
【发布时间】:2017-03-14 20:54:05
【问题描述】:

编辑:我正在开发 SQL Server 2012

我正在开展一个项目,其中表中的两列需要在更新时记录它们的数据。因此,为了让它工作,当有人决定更新地址或邮政编码并保存时,审计表需要记录列中的先前值 before更新。

我已经开始设置一个审核表来保存所需的数据

CREATE TABLE Customer_Audit
(
Cust_UpdateID int IDENTITY (1,1),
Cust_User char (8),
Cust_Update_Date date,
Cust_ID int, 
CustomerAddresss nvarchar (255),
CustomerZipCode nvarchar (255),

CONSTRAINT [pk_Cust_UpdateID] PRIMARY KEY (Cust_UpdateID)

)

我面临的唯一问题是建立一个实际的触发器查询来用客户表中的所需数据填充审计表。有人告诉我 AFTER UPDATE 触发器是理想的,但我不知道如何正确设置它并获取我需要的数据并填充审计表本身。

有人可以向我推荐并告诉我如何设置可以执行我想做的事情的触发器吗?

【问题讨论】:

  • 用您正在使用的数据库标记您的问题(根据语法可能是 SQL Server)。
  • 您的原始表是否包含相同的列Cust_IDCustomerAddressCustomerZipCode?你原来的表的名字是Customer吗?
  • 原始表包含这 3 列,是的,它被称为 Customer
  • 这是我见过的最好的解决方案,适合您尝试做的所有事情:Quick And Easy Audit Tables - Dave Britten

标签: sql sql-server sql-server-2012


【解决方案1】:

您可以在触发器中使用“已删除”和“插入”表:https://msdn.microsoft.com/en-us/library/ms191300(v=sql.110).aspx

CREATE TRIGGER Customer_update_trig ON Customer
AFTER UPDATE
AS
BEGIN
  INSERT INTO Customer_Audit (Cust_User, Cust_Update_Date, Cust_ID, CustomerAddresss, CustomerZipCode)
  SELECT d.Cust_User,
    d.Cust_Update_Date,
    d.Cust_ID,
    d.CustomerAddresss, --sic
    d.CustomerZipCode
  FROM deleted d
END

-- OR for auto generated user and timestamp

CREATE TRIGGER Customer_update_trig ON Customer
AFTER UPDATE
AS
BEGIN
  INSERT INTO Customer_Audit (Cust_User, Cust_Update_Date, Cust_ID, CustomerAddresss, CustomerZipCode)
  SELECT CURRENT_USER,
    GETDATE(),
    d.Cust_ID,
    d.CustomerAddresss, --sic
    d.CustomerZipCode
  FROM deleted d
END

当然,您也希望将您的架构名称也放在那里(如果使用默认值,则为“dbo”)。并仔细检查它们与原始表匹配的列名。

对于您的审核策略,您需要决定是只想在更新后记录,还是急切地记录原始插入。

从您的审计表中优化SELECT 的另一件事是,如果您有一个Cust_Record_Start_TimeCust_Record_End_Time 来提供记录有效时间的范围,那么您可以拥有更有效的WHERE 子句。使用该数据查询某个时间点要容易得多。

我没有 SQL Server,所以我无法测试语法,但概念应该存在。

此外,如果添加此触发器会为您的 UPDATE 语句增加太多时间,您可以查看 Service Broker:https://msdn.microsoft.com/en-us/library/bb522893(v=sql.110).aspx

它允许异步保证“消息”,可以非常接近实时地更新您的审计表。

【讨论】:

  • 虽然这回答了 OP 的问题:a) 这更适合作为评论。 b)仅链接的答案应在正文中包含相关文本和 c)一般来说,这是一个低质量的问题,不应该为了网站的质量而回答
  • 感谢您的反馈,我会尝试从 OP 获取更多信息并添加相关示例。
  • 谢谢你的例子。在 INSERT INTO 部分之后,我有点困惑。
  • SELECT d.Cust_user、d.Cust_update_date 等是什么意思?
  • 另外我忘了提到一些字段会被自动添加,它们不会是客户表的一部分。像 Cust_user 和 Cust_update_date 一样会自动生成
【解决方案2】:

您可以在触发器中引用旧值和新值,从而可以引用所需数据并将其导入审计表。从您的描述中不清楚究竟从 Customer 表中获取了哪些数据,因此我假设所有审计字段在 Customer 表中都有等效字段,但 Cust_UpdateID 除外。

CREATE TRIGGER update_audit_table
    AFTER UPDATE
    ON Customer
    BEGIN
      INSERT INTO Customer_Audit(Cust_User, Cust_ID, Cust_Update_Date, CustomerAddress, CustomerZipCode)
      VALUES (OLD.Cust_User, OLD.Cust_ID, OLD.Cust_Update_date, OLD.CustomerAddress, OLD.CustomerZipCode)
    END

注意:在触发器中,OLD 是对更改前行的引用,NEW 是对更改后行的引用。

【讨论】:

  • Cust_User、Cust_Update_Date 是应该从触发器自动生成的字段。我应该指定的,对不起。如何在表中设置它以自动生成这些字段,但从 Customer 表中获取其他字段。
  • 您希望这些字段跟踪什么?您可以在触发器中将这些字段的值设置为您想要的任何值,我只是不清楚您实际上要在这些列中存储哪些数据。
  • 我只是想在客户表更新时存储 ID、地址和邮政编码。这就是触发器的全部意义,它意味着获取这些值并存储它们,以便记录它们。每当它们更新时。
  • 仍然不确定要为 Cust_User 和 Cust_Update_Date 字段生成什么数据。如果 Cust_Update_Date 只是创建审计记录时的时间戳,我只会使该列具有当前时间戳的默认值,而不是在触发器中设置它。我不清楚 Cust_User 列中存储的数据是什么。
猜你喜欢
  • 2011-01-15
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多