I’m still working on this database for a small retail store (a scenario, thankfully!) and am currently trying to fix this issue with a trigger.
The relevant entities are Customer, Payment and Order. Payment is a link entity between the other two, so one Customer could make many payments and one order could have many payments (unusual but still possible) and that’s all fine.
The trigger:
CREATE OR REPLACE TRIGGER Check_Payment_Status
BEFORE UPDATE OF Order_Status ON Customer_Order
for each row
DECLARE paymentStatus payment.payment_status%type;
BEGIN
select payment.payment_status into paymentStatus
from payment
where order_no = :new.order_no;
IF (paymentStatus ='Failed' OR paymentStatus IS NULL ) then
RAISE_APPLICATION_ERROR(-20103, 'The full payment has not been made so the order cannot be processed further until then.');
update customer_order set order_status='Delayed' where order_no= :new.order_no;
END IF;
IF (paymentStatus ='Successful' ) then
update payment set payment_date=SYSDATE where order_no= :new.order_no;
END IF;
END;
.
run
It works okay at the moment. Basically, before a customer’s order can be flagged as “Dispatched” the payment status must be “Successful”. If it’s null or “Failed” the trigger will be like “oh no you don’t!” (but in more formal words) which is working as intended. However, if one applies the business rule “an order can have many payments” the trigger needs to check all relevant payments which is where I get this error, as the SELECT INTO statement is intending to return one row only.
I’ve read up on Cursors a bit but I think I’m going a bit too far here – would anyone suggest some solutions, please?
Well, if an order can have multiple payments, how do you decide if it is paid in full? Presumably each payment has an amount, and the order has a total amount due, so you need to check that the full amount has been paid. Seems to me you can do this by getting the sum of all successful payments then comparing it to the total amount due. The basic query would be: