我需要创建一个触发器,将有关价格变化的信息插入另一个表中。下面我提出我的解决方案。
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
当我只更新一条记录时,一切都很好。问题是当我尝试更新许多记录时,我看到下面的错误:
Msg 512,Level 16,State 1,Procedure trig1,Line 41
子查询返回的值超过1。当子查询遵循=,!=,&lt;,&lt; =,&gt;,&gt; =或子查询用作表达式时,不允许这样做。该 声明已被终止。
有谁知道如何解决这个问题?
答案 0 :(得分:2)
问题是触发器是在语句库上触发的,而不是在行基础上触发的。这意味着对语句中更新的所有行触发一次触发器,因此inserted
和deleted
表可能包含多行。
但是,您的触发器代码不会考虑这一点,从而引发错误。
请改为尝试:
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
答案 1 :(得分:2)
为每个Update语句触发触发器,而不是为update语句中的每一行触发。您根本不需要任何这些变量,只需从inserted
和deleted
表中选择数据(旧的和新的)数据并将其直接插入到审计表中,就像这样...... ...
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