2016-12-27 51 views
0

我需要創建一個觸發器,它將有關價格變化的信息插入另一個表中。下面我介紹我的解決方案。使用有關表更新的日誌信息創建觸發器

CREATE TABLE Production.Products_AUDIT 
(
    auditid  INT   NOT NULL IDENTITY, 
    productid INT   NULL, 
    old_price MONEY  NOT NULL, 
    new_price MONEY  NOT NULL, 

    CONSTRAINT PK_Products_AUDIT PRIMARY KEY(auditid), 
    CONSTRAINT FK_Products_AUDIT_AUDIT 
     FOREIGN KEY(productid) REFERENCES Production.Products(productid) 
); 

INSERT INTO Production.Products_AUDIT VALUES (1, 18 , 20) 
INSERT INTO Production.Products_AUDIT VALUES (2, 19 , 31) 

DELETE FROM Production.Products_AUDIT 

SELECT unitprice 
FROM Production.Products_AUDIT as p1 
INNER JOIN Production.Products as p2 on p1.productid = p2.productid 

CREATE TRIGGER trig1 
ON Production.Products 
FOR UPDATE 
AS 
    declare @prodId INT 
    declare @oldPrice MONEY 
    declare @newPrice MONEY 

    SET @prodId = (SELECT i.productid 
        FROM inserted as i 
        INNER JOIN Production.Products as pp on i.productid = pp.productid) 
    SET @oldPrice = (SELECT i.unitprice 
        FROM deleted as i 
        INNER JOIN Production.Products as pp on i.productid = pp.productid) 

    SET @newPrice = (SELECT i.unitprice 
        FROM inserted as i 
        INNER JOIN Production.Products as pp on i.productid = pp.productid) 

    INSERT INTO Production.Products_AUDIT 
    VALUES(@prodId, @oldPrice, @newPrice) 

    UPDATE Production.Products 
    SET unitprice = 45 
    WHERE productid < 2 

    SELECT * FROM Production.Products_AUDIT 

當我只更新一條記錄時,一切正常。問題是,當我嘗試更新多條記錄,然後我看到下面的錯誤:

消息512,級別16,狀態1,過程TRIG1,41號線
子查詢返回多個值。當子查詢遵循=,!=,<,< =,>,> =或當子查詢用作表達式時,這是不允許的。 聲明已被終止。

有誰知道如何解決這個問題?

+0

@XING不,這不是個好主意,尤其是在觸發器中。基於集合的方法是這裏需要的。 –

回答

2

問題是觸發器是在一個語句庫上觸發的,而不是在行的基礎上觸發的。這意味着對於語句中更新的所有行,您的觸發器會被觸發一次,因此inserteddeleted表可能包含多行。

但是,您的觸發代碼沒有考慮到這一點,從而引發錯誤。

試試這個:

CREATE TRIGGER Products_ForUpdate 
ON Production.Products 
FOR UPDATE 
AS 

    INSERT INTO Production.Products_AUDIT 
    SELECT i.productid, d.unitprice, i.unitprice 
    FROM inserted as i 
    INNER JOIN Production.Products as pp on i.productid = pp.productid 
    INNER JOIN deleted as d ON pp.productid = d.productid 
2

扳機在更新語句解僱的每個更新語句不是每一行。你不需要任何這些變量的所有,只是從inserteddeleted表中選擇數據(舊的和新的)數據,並將其直接插入到審計表中,這樣的事情........

CREATE TRIGGER trig1 
ON Production.Products 
FOR UPDATE 
as 
BEGIN 
SET NOCOUNT ON; 

    INSERT INTO Production.Products_AUDIT (productid , Old_Price , New_Price) 
    SELECT pp.productid 
     , d.unitprice AS OldPrice 
     , i.unitprice AS NewPrice 
    FROM Production.Products as pp 
    INNER JOIN inserted i ON i.productid = pp.productid 
    INNER JOIN deleted d ON d.productid = pp.productid 

END 
+0

謝謝。一切都很好。 –