2016-11-18 20 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

相關問題