2016-11-18 41 views
0

我创建了一个名为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; 
+0

你的表有7列,但你的'SELECT'只有5个字段。 在你的CREATE TABLE脚本中,AuditID是一个PRIMARY KEY,但它不是'IDENTITY'。意思是,如果你想在表中插入一条记录,你必须指定一个“AuditID”。 此外,你没有选择任何'DateUpdated'。也许你希望这有一个默认的'GETDATE()'? – Santi

回答

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; 

所以,你似乎有事情的几个问题,我会看看我能走你通过他们和固定的1路。首先,你说你想要ProductAudit保存值“AFTER”它们已被更新,但是你的代码和术语Audit建议你想将旧值(已删除)存储到审计表中而不是新值,所以这是我工作的假设从。

您显示的代码有两个主要问题。

  • ROLLBACK TRAN - 这有点像一个撤销按钮,将回滚事务中的所有语句可能不只是你是想跟踪更新的更多。这意味着你的数据实际上不会被更新。
  • (SELECT CategoryId FROM Inserted) - 上触发基于集合的操作进行评估不是标值所以如果超过1行更新的表inserted将有超过1 CateogryId。因此,它会选取数据集中的最后一行,并且只有该行将被插入到您的Audit表中。

请注意,您可以使用deletedinserted表获取所需的信息。技术上你只需要deleted如果你想存储记录,不管是什么。我展示了如何使用它们来检测记录是否实际发生了变化,然后只记录是否有记录。

+0

您需要在您的插入中使用“AuditID”,或者在我认为的列中使用“IDENTITY”。在我的SQL Server修补程序中:'不能将值NULL插入列'AuditID',表'dbo.ProductsAudit';列不允许有空值。 INSERT失败。' – Santi

+0

@Santi是的,我只关注他的触发器,而不是他的其他陈述,但这是一个很好的补充,所以OP会希望注意到 – Matt

相关问题