使用触发器将更新前的值放入另一个表中

时间:2016-11-18 21:48:45

标签: sql sql-server triggers

我创建了一个名为ProductsAudit的表,用于在使用触发器更新后保存MyGuitarShop产品表中的值,但我似乎无法使其工作。我在SQL Server中这样做。

所以我需要做的是更新产品时,它会将旧值存储到ProductsAudit表中。

CREATE TABLE ProductsAudit
(
AuditID int NOT NULL,
CategoryID int,
ProductCode varchar(10) NOT NULL,
ProductName varchar(255) NOT NULL,
ListPrice money NOT NULL,
DiscountPercent money NOT NULL,
DateUpdated datetime
PRIMARY KEY (AuditID)
FOREIGN KEY (CategoryID) REFERENCES Categories(CategoryID)
)

CREATE TRIGGER Products_UPDATE2
ON Products
AFTER UPDATE
AS
BEGIN;
ROLLBACK TRAN
INSERT INTO ProductsAudit
SELECT CategoryID, ProductCode, ProductName, ListPrice, DiscountPercent
FROM Deleted
WHERE CategoryID = (SELECT CategoryID FROM Inserted);
PRINT 'Old data sent to ProductsAudit'
END;

UPDATE Products
SET ListPrice = 79.43
WHERE ProductID = 3;

1 个答案:

答案 0 :(得分:0)

CREATE TABLE ProductsAudit
(
AuditID int NOT NULL IDENTITY(1,1),
CategoryID int,
ProductCode varchar(10) NOT NULL,
ProductName varchar(255) NOT NULL,
ListPrice money NOT NULL,
DiscountPercent money NOT NULL,
DateUpdated datetime DEFAULT (GETDATE()),
PRIMARY KEY (AuditID),
FOREIGN KEY (CategoryID) REFERENCES Categories(CategoryID)
)

CREATE TRIGGER Products_UPDATE2
ON Products
AFTER UPDATE
AS
BEGIN;

    INSERT INTO ProductsAudit (CategoryID, ProductCode, ProductName, ListPrice, DiscountPercent, DateUpdated)
    SELECT
       d.CategoryID
       ,d.ProductCode
       ,d.ProductName
       ,d.ListPrice
       ,d.DiscountPercent
       ,DateUpdated = GETDATE() -- may consider adding default to the table to handle this part
    FROM
       deleted d
       LEFT JOIN inserted i
       ON d.CategoryID= i.CategoryID --is this the Product PrimaryKey Column?
    WHERE
       ISNULL(d.CategoryID,-1) <> ISNULL(i.CategoryID,-1)
       OR ISNULL(d.ProductCode,'') <> ISNULL(i.ProductCode,'')
       OR ISNULL(d.ProductName,'') <> ISNULL(i.ProductName,'')
       OR ISNULL(d.ListPrice,-1) <> ISNULL(i.ListPrice,-1)
       OR ISNULL(d.DiscountPercent,-1000) <> ISNULL(i.DiscountPercent,-1000)

    PRINT 'Old data sent to ProductsAudit'

END;

UPDATE Products
SET ListPrice = 79.43
WHERE ProductID = 3;

所以你似乎有一些问题正在发生,我会看看我是否可以引导你完成它们和一种修复方法。首先,你说你希望ProductAudit保持值“AFTER”它们已被更新但你的代码和术语审计建议你想将OLD值(删除)存储到审计表而不是新值,这是我工作的假设从

您展示的代码存在两个主要问题。

  • ROLLBACK TRAN - 这有点像撤消按钮,可以回滚事务中的所有语句,这些语句可能不仅仅是您想要跟踪的更新。这意味着您的数据实际上不会得到更新。
  • (SELECT CategoryId FROM Inserted) - 触发器是针对基于集合的操作而非标量值进行评估的,因此如果大于1,则表格inserted将超过1 CateogryId行已更新。因此,它会选择数据集中的最后一行,并且只将该行插入到Audit表中。

请注意,您可以使用deletedinserted表来获取所需信息。从技术上讲,如果你想存储一条记录,你只需要deleted。我将展示如何使用它们来检测记录是否实际发生了更改,然后只记录是否存在更改。