如何一一删除行,以使触发器不会引发错误

时间:2020-07-05 10:47:25

标签: sql-server ssms

我有一个触发器,当在InvoiceDetails中删除一行时,该行将被复制到InvoiceDetailsHistory。当我执行sql“ Delete From InvoiceDetails”时,出现错误消息:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

我想是因为我要一次删除所有行。我该如何解决?这是我的触发器:

ALTER trigger [dbo].[deleteinvoicedetails]       
on [dbo].[InvoiceDetails]
AFTER DELETE 
AS
DECLARE @InvoiceID int,@FoodID int,@quantity int,@UnitPrice float,@totalprice float
BEGIN
SET @InvoiceID = (Select InvoiceID from deleted)
SET @FoodID = (Select FoodID from deleted)
SET @quantity = (Select quantity from deleted)
SET @UnitPrice = (Select UnitPrice from deleted)
SET @totalprice = (Select totalprice from deleted)
INSERT INTO InvoiceDetailsHistory VALUES (@InvoiceID,@FoodID,@quantity,@UnitPrice,@totalprice)
END

2 个答案:

答案 0 :(得分:3)

您是否考虑过固定扳机?假设已删除的行是ONE行-可能不是,则此插入是可恶的,并且逐行删除行只会使问题隐藏起来,直到弹出为止。

正确的方法是:

  • 摆脱所有变量。他们没有道理。

  • 使用Inser INTO .... SELCT语法选择已删除的数据,并将其插入到发票明细历史记录表中。基本上,这将需要使用已删除的表作为源(在insert into的选择部分中)。

这也将大大提高速度-您可以使用bascailyl一次(一组)运行许多冗余操作,而不使用SQL。即使您的代码不会损坏(一行),也可以一次选择所有SET。您可以选择多个变量,然后一次选择多个变量。

但是实际上,在您的情况下,变量没有任何意义。您可以通过从已删除表中选择数据来直接插入历史表。

答案 1 :(得分:2)

您显然还在学习,所以让我举一个@tomtom所指的例子...

ALTER trigger [dbo].[deleteinvoicedetails]       
on [dbo].[InvoiceDetails]
AFTER DELETE 
AS
BEGIN
INSERT INTO
  InvoiceDetailsHistory
SELECT
  InvoiceID,
  FoodID, 
  Quantity,
  UnitPrice,
  Totalprice
FROM
  deleted
END

无论删除多少行,此方法都有效。

相关问题