我有一个名为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'不能具有任何已启用的触发器
答案 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
语句。