2

I have a table called INVOICE which stores bill information about an order/orders, one of the columns in this table is a column named paid which is a type of bit. As its name indicates, this column indicates whether the specific order/orders bill is paid or not.

I have another table named RECEIPT, this table stores information about any payment processes for a specific invoice.

So every time user pay an amount for the specified invoice, a new receipt record is created.

Now What I'm trying to do is to create a trigger that updates the paid column in the INVOICE table and set it to 1. This update process should be triggered in case of that the sum of receipts that belong to the invoice is equal to the amount_due in the INVOICE table.

In other words, if invoice due amount= 100$ and the user paid 50$ then, late he paid the other 50$ The paid column in the INVOICE table should be set to 1 as the total payments are equal to the invoice due amount

This is the trigger I've created to achieve the above

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;

it compiled successfully but at run time I've get the below error:

The target table 'RECEIPT' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause

Husain Alhamali
  • 823
  • 4
  • 17
  • 32
  • The problem is in a piece of code you're not showing us, that is performing an `INSERT ... OUTPUT ...`, and, as the error message is also stating (quite clearly, IMO), it's not using `INTO`. – Damien_The_Unbeliever Jan 15 '16 at 09:13
  • Also, your trigger is broken. `INVOICE.invoice_id = (SELECT inserted.invoice_id FROM inserted)` is going to produce an error when `inserted` contains multiple rows. – Damien_The_Unbeliever Jan 15 '16 at 09:14
  • Is there auto incremented identity column for Receipt table? Please refer: http://www.sql-server-helper.com/error-messages/msg-334.aspx – D Mayuri Jan 15 '16 at 09:20

1 Answers1

2

I think personally that you should update the paid status outside the scope of triggers. If you perform an INSERT into RECEIPT, you can execute the UPDATE INVOICE ... statement right after that (inside a TRANSACTION of course). A lot cleaner and predictable that way.

As to the error you are getting it's hard to say what is causing that based on the information you gave us. Perhaps the TRIGGER is triggering other TRIGGERs that produce the error you are getting? The statement you provided simply doesn't have an OUTPUT statement.

In any case, the statement you provided is not written correctly (as Damien pointed out) because the inserted table can have multipe rows. This is a rewrite to correct at least that part:

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;

But as I mentioned earlier you probably not be doing this from a TRIGGER. Execute this statement from your program right after any INSERT/UPDATE. Alternatively, write a Stored Procedure for inserting into RECEIPT and execute the UPDATE statement right after the INSERT.

TT.
  • 15,774
  • 6
  • 47
  • 88
  • Thanks so much, I'm not that familiar with SQL syntaxes, but as I understand from the error, there must be an `INTO` clause if there was an `OUTPUT` statement, but actually my code and yours doesn't include any `OUTPUT` statement. I don't know if I'm understanding that properly, thanks again @TT – Husain Alhamali Jan 15 '16 at 10:12
  • @AliAlhamaly There's no OUTPUT clause in this statement. That's your clue that you should be looking elsewhere for the cause of the problem you're having. GL! – TT. Jan 15 '16 at 10:16
  • I think I figured out the cause of the problem, the id column in the `RECEIPT` table is an auto-incremented identity column. Doing some search on google I found that an enabled trigger that includes an update statement cannot be triggered on a table that contains such id column, I mean an auto-incremented identity table. So I need now to workaround this problem to bypass this error. But still not sure if this is the actual cause – Husain Alhamali Jan 15 '16 at 10:36
  • 1
    This [Stackoverflow thread](https://stackoverflow.com/questions/13198476/cannot-use-update-with-output-clause-when-a-trigger-is-on-the-table) seems to be about your case. You are inserting into/updating receipt and the insert statement apparantly has an OUTPUT clause. Either you add an `INTO ...` to the statement, or rewrite your statement to not have an OUTPUT clause. – TT. Jan 15 '16 at 10:43