子查询返回的值超过1。当子查询跟随=或子查询用作表达式时,这是不允许的?

时间:2014-02-23 12:00:48

标签: sql-server tsql triggers

我想在一个表中插入值后更新多个表和值,因此我创建了一个触发器。它适用于一行插入,但是一旦插入更多行,SQL Server就会出现以下错误:

  

子查询返回的值超过1。当子查询跟随=或子查询用作表达式时,不允许这样做?

这是我的触发器:

CREATE TRIGGER [dbo].[tbl_Sales_ForInsert]
ON [dbo].[SALES] 
FOR INSERT
AS
BEGIN
  DECLARE @ITEMMODEL varchar(100)

  SELECT @ITEMMODEL = ITEM_MODEL FROM inserted

  UPDATE SALES 
  SET PROFIT = TOTAL_PRICE - (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL = @ITEMMODEL) * (SELECT RATE FROM ITEM_DETAILS WHERE ITEM_MODEL = @ITEMMODEL) 
  WHERE ITEM_MODEL = @ITEMMODEL

  UPDATE ITEM_DETAILS 
  SET QUANTITY = QUANTITY - (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL = @ITEMMODEL) 
  WHERE ITEM_MODEL = @ITEMMODEL

  --UPDATE ITEM_DETAILS SET AMOUNT = AMOUNT - (SELECT RATE FROM ITEM_DETAILS WHERE ITEM_MODEL=@ITEMMODEL) * (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL=@ITEMMODEL) where ITEM_MODEL=@ITEMMODEL
END

当我第一次在SALES表中插入数据时,更新成功但是第二次它给出了上面的错误,记住ITEM_MODEL是SALES表中的外键约束。

我一直在遭受这个错误,任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:8)

您的根本缺陷是,您似乎希望触发器每行一次 - 这在SQL Server中是 NOT 。相反,触发器会在每个语句时触发,而伪表Inserted可能包含多行

鉴于该表可能包含多行 - 您希望在这里选择哪一行?

SELECT @ITEMMODEL = ITEM_MODEL FROM inserted

未定义 - 您可以从Inserted中的任意行获取值。

您需要使用Inserted WILL 包含多行的知识重写整个触发器!您需要使用基于集合的操作 - 不要只期望Inserted中的一行!

因此,在您的情况下,您的触发器代码应如下所示:

CREATE TRIGGER [dbo].[tbl_Sales_ForInsert]
ON [dbo].[SALES] 
FOR INSERT
AS
BEGIN
   -- update the dbo.Sales table, set "PROFIT" to the difference of 
   -- TOTAL_PRICE and (QUANTITY * RATE) from the "Inserted" pseudo table
   UPDATE s
   SET s.PROFIT = i.TOTAL_PRICE - (i.QUANTITY * i.RATE) 
   FROM dbo.Sales s
   INNER JOIN Inserted i ON i.ITEM_MODEL = s.ITEM_MODEL

   -- update the dbo.ITEM_DETAILS table
   UPDATE id
   SET id.QUANTITY = id.QUANTITY - i.Quantity
   FROM dbo.ITEM_DETAILS id
   INNER JOIN Inserted i ON id.ITEM_MODEL = i.ITEM_MODEL
END

答案 1 :(得分:0)

Marc_s是正确的,期望插入的伪表包含多行。如果子查询仅限于具有TOP(1)的一行,则存在查询可能有效的情况。

  UPDATE SALES 
  SET PROFIT = TOTAL_PRICE - (SELECT TOP(1) QUANTITY FROM SALES WHERE ITEM_MODEL = @ITEMMODEL) 
  * (SELECT TOP(1) RATE FROM ITEM_DETAILS WHERE ITEM_MODEL = @ITEMMODEL) 
  WHERE ITEM_MODEL = @ITEMMODEL