【问题标题】:I am looking for a way for a trigger to insert into a second table only where the value in table 1 changes我正在寻找一种方法,让触发器仅在表 1 中的值发生变化时才插入到第二个表中
【发布时间】:2015-02-17 20:18:34
【问题描述】:

我正在寻找一种方法,让触发器仅在表 1 中的值发生变化时才插入到第二个表中。它本质上是一个审计工具,用于捕获所做的任何更改。表 1 中的字段是价格,我们要编写其他字段。

这是我目前所拥有的。

CREATE  TRIGGER zmerps_Item_costprice__update_history_tr ON [ITEM] 
FOR UPDATE
AS
insert into zmerps_Item_costprice_history
        select  NEWID(), -- unique id
                GETDATE(),  -- CURRENT_date
                'PRICE_CHANGE', -- reason code
                a.ima_itemid, -- item id
                a.ima_price-- item price

            FROM  Inserted b inner join item a
                    on b.ima_recordid = a.IMA_RecordID

该表仅包含唯一标识符、日期、参考(项目)和更改的字段(价格)。它记录了任何变化,而不仅仅是价格变化

【问题讨论】:

  • 您可以编辑您的问题并格式化触发代码以便我们阅读吗?因为它坐在那里,所以很难破译应该在那里的东西,因为格式丢失了,而且里面到处都是 cmets。
  • 执行更新查询时,更改的行同时位于inserteddeleted 中(分别具有新值和旧值)。您可以在主键上加入这些以获取更新的行,然后您可以检查是否只有价格发生了变化。它可能比连接整个表要快一些。

标签: sql sql-server triggers


【解决方案1】:

就这么简单吗?我移动了一些代码,因为在列之间的逗号之后的 cmets 维护起来很痛苦。您还应该始终在插入语句中指定列。如果您的表发生更改,此代码仍然有效。

CREATE  TRIGGER zmerps_Item_costprice__update_history_tr ON [ITEM] 
FOR UPDATE
AS
insert into zmerps_Item_costprice_history
(
    UniqueID
    , CURRENT_date
    , ReasonCode
    , ItemID
    , ItemPrice
)
    select  NEWID()
        , GETDATE()
        , 'PRICE_CHANGE'
        , d.ima_itemid
        , d.ima_price
    FROM Inserted i 
    inner join deleted d on d.ima_recordid = i.IMA_RecordID
        AND d.ima_price <> i.ima_price

【讨论】:

  • 这个只处理如果有价格变化,OP想捕捉任何列的任何变化......The field in table 1 is price and we want to write additional fields
  • 如果 ima_price 列允许为空,则应为 AND (d.ima_price i.ima_price OR d.ima_price IS NULL AND i.ima_price IS NOT NULL OR d.ima_price IS NOT NULL AND i .ima_price 为空)
  • 我将其解释为上述代码将处理的价格变化。如果不是这种情况,那么 OP 稍微调整一下应该很简单。
  • 我还假设任何用于存储价格的表都不允许价格为 NULL。但同样,没有更多细节我们不知道。
  • 继续稍微调整它以处理其他列中的更改 :) 让我们看看它是如何完成的 :)
【解决方案2】:

由于您没有提供任何其他列名,我在下面的示例中使用了 Column2 和 Column3 以及“其他”列名。

您可以在下面的代码中扩展添加更多列。

关于以下查询的概述:

加入已删除和插入的表(仅针对已更改的行)加入表本身将导致对根本未更改的行进行不必要的处理。

如果列的值没有改变,我已经使用 NULLIF 函数来产生一个空值。

将所有列转换为相同的数据类型(反透视所需)。

使用 unpivot 从结果集中消除所有空值。

unpivot 还会为您提供已取消透视的列名。

CREATE  TRIGGER zmerps_Item_costprice__update_history_tr 
ON [ITEM] 
FOR UPDATE
AS 
BEGIN
  SET NOCOUNT ON ;

WITH CTE AS (
SELECT  CAST(NULLIF(i.Price   , d.Price)    AS NVARCHAR(100)) AS Price
       ,CAST(NULLIF(i.Column2 , d.Column2)  AS NVARCHAR(100)) AS Column2
       ,CAST(NULLIF(i.Column3 , d.Column3)  AS NVARCHAR(100)) AS Column3
FROM dbo.inserted i 
INNER JOIN dbo.deleted d ON i.IMA_RecordID = d.IMA_RecordID
WHERE i.Price   <> d.Price
 OR   i.Column2 <> d.Column2
 OR   i.Column3 <> d.Column3
 )
 INSERT INTO zmerps_Item_costprice_history
               (unique_id, [CURRENT_date], [reason code], Item_Value)
 SELECT  NEWID()
        ,GETDATE()
        ,Value
        ,ColumnName + '_Change'
 FROM CTE UNPIVOT (Value FOR ColumnName IN (Price , Column2, Column3) )up

END

【讨论】:

    【解决方案3】:

    我正确理解您的问题,您想要记录更改当且仅当列价格值发生更改时,您不需要记录任何其他列更改

    这是你的代码

    CREATE  TRIGGER zmerps_Item_costprice__update_history_tr ON [ITEM] 
    FOR UPDATE
    AS
    if update(ima_price)
    insert into zmerps_Item_costprice_history
        select  NEWID(), -- unique id
                GETDATE(),  -- CURRENT_date
                'PRICE_CHANGE', -- reason code
                a.ima_itemid, -- item id
                a.ima_price-- item price
    
            FROM  Inserted b inner join item a
                    on b.ima_recordid = a.IMA_RecordID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多