如果语句包含没有INTO子句

时间:2016-01-15 08:56:34

标签: sql-server

我有一个名为INVOICE的表,它存储有关订单/订单的帐单信息,此表中的一列是一个名为paid的列,它是一种位。如其名称所示,此列指示是否支付特定订单/订单帐单。

我有另一个名为RECEIPT的表,此表存储有关特定发票的任何付款流程的信息。

因此,每当用户为指定发票支付金额时,都会创建新的收据记录。

现在我要做的是创建一个触发器来更新paid表中的INVOICE列并将其设置为1.如果是这样,则应触发此更新过程属于发票的收据总和等于amount_due表中的INVOICE

换句话说,如果发票到期金额= 100美元 并且用户支付了50美元 然后,他迟到了另外50美元 INVOICE表中的paid列应设置为1,因为总付款等于发票到期金额

这是我为实现上述目标而创建的触发器

CREATE TRIGGER tg_invoice_payment ON RECEIPT
AFTER INSERT
AS
BEGIN
UPDATE INVOICE
SET paid = 1 
WHERE INVOICE.invoice_id = (SELECT inserted.invoice_id FROM inserted)
AND (SELECT SUM(RECEIPT.amount_paid) 
FROM RECEIPT 
JOIN inserted ON RECEIPT.receipt_id = inserted.receipt_id 
WHERE RECEIPT.invoice_id = inserted.invoice_id) = (SELECT INVOICE.amount_due 
FROM INVOICE 
JOIN inserted ON INVOICE.invoice_id = inserted.invoice_id 
WHERE INVOICE.invoice_id = inserted.invoice_id)
END;

它编译成功,但在运行时我得到以下错误:

  

如果语句包含没有INTO子句的OUTPUT子句,则DML语句的目标表'RECEIPT'不能具有任何已启用的触发器

1 个答案:

答案 0 :(得分:1)

我个人认为您应该更新触发范围之外的paid状态。如果您在INSERT中执行RECEIPT,则可以在此之后立即执行UPDATE INVOICE ...语句(当然在TRANSACTION内)。那种方式更加清洁和可预测。

至于你得到的错误很难说根据你给我们的信息导致了什么。也许TRIGGER会触发其他产生错误的TRIGGER?您提供的声明根本没有OUTPUT声明。

在任何情况下,您提供的语句都没有正确写入(正如Damien指出的那样),因为inserted表可以有多行。这是重写至少纠正那部分:

CREATE TRIGGER tg_invoice_payment ON RECEIPT
AFTER INSERT
AS
BEGIN
    UPDATE
        INVOICE
    SET 
        paid = 1
    FROM
        inserted AS ins
        INNER JOIN INVOICE AS inv ON
            inv.invoice_id=ins.invoice_id
    WHERE
        inv.amount_due=(
            SELECT 
                SUM(r.amount_paid) 
            FROM 
                RECEIPT AS r
            WHERE
                r.receipt_id=ins.invoice_id
        );
END;

但正如我之前提到的,你可能不会从TRIGGER那样做。在任何INSERT/UPDATE之后立即从您的程序执行此语句。或者,编写存储过程以插入RECEIPT并在UPDATE之后立即执行INSERT语句。