| | 1 | = Prevention of ordering unavailable products |
| | 2 | |
| | 3 | === Description |
| | 4 | This trigger prevents customers from placing an order for a product when the requested quantity is greater than the quantity currently available in the store. |
| | 5 | |
| | 6 | The trigger checks the available quantity before a product is added to an order. If there is not enough stock, the operation is rejected and an error message is returned. |
| | 7 | |
| | 8 | This guarantees that the database cannot contain orders for products that are not available in the required quantity. |
| | 9 | |
| | 10 | ==== Tables involved |
| | 11 | - Product |
| | 12 | - Order |
| | 13 | - includes |
| | 14 | - sells |
| | 15 | |
| | 16 | ==== Type of trigger |
| | 17 | - BEFORE INSERT |
| | 18 | - BEFORE UPDATE |
| | 19 | |
| | 20 | Activated on the `includes` table. |
| | 21 | |
| | 22 | ==== SQL Code |
| | 23 | {{{#!sql |
| | 24 | CREATE OR REPLACE FUNCTION check_product_availability() |
| | 25 | RETURNS TRIGGER |
| | 26 | LANGUAGE plpgsql |
| | 27 | AS $$ |
| | 28 | DECLARE |
| | 29 | v_available_quantity INT; |
| | 30 | v_order_quantity INT; |
| | 31 | BEGIN |
| | 32 | -- Get the quantity requested by the order |
| | 33 | SELECT quantity |
| | 34 | INTO v_order_quantity |
| | 35 | FROM "order" |
| | 36 | WHERE order_num = NEW.order_num; |
| | 37 | |
| | 38 | -- Get the currently available quantity of the product |
| | 39 | SELECT quantity |
| | 40 | INTO v_available_quantity |
| | 41 | FROM sells |
| | 42 | WHERE code = NEW.code; |
| | 43 | |
| | 44 | -- Check whether the product exists |
| | 45 | IF v_available_quantity IS NULL THEN |
| | 46 | RAISE EXCEPTION |
| | 47 | 'Product % is not available in any store.', |
| | 48 | NEW.code; |
| | 49 | END IF; |
| | 50 | |
| | 51 | -- Check whether there is enough stock |
| | 52 | IF v_order_quantity > v_available_quantity THEN |
| | 53 | RAISE EXCEPTION |
| | 54 | 'Insufficient stock for product %. Available: %, requested: %.', |
| | 55 | NEW.code, |
| | 56 | v_available_quantity, |
| | 57 | v_order_quantity; |
| | 58 | END IF; |
| | 59 | |
| | 60 | RETURN NEW; |
| | 61 | END; |
| | 62 | $$; |
| | 63 | |
| | 64 | |
| | 65 | CREATE TRIGGER trg_check_product_availability |
| | 66 | BEFORE INSERT OR UPDATE |
| | 67 | ON includes |
| | 68 | FOR EACH ROW |
| | 69 | EXECUTE FUNCTION check_product_availability(); |
| | 70 | |
| | 71 | }}} |
| | 72 | |
| | 73 | === Logic explanation |
| | 74 | |
| | 75 | Before a product is added to an order, the trigger: |
| | 76 | |
| | 77 | **1.** Identifies the order using NEW.order_num. |
| | 78 | **2.** Retrieves the requested quantity from the ORDER table. |
| | 79 | **3.** Identifies the product using NEW.code. |
| | 80 | **4.** Retrieves the available quantity from sells. |
| | 81 | **5.** Compares the requested quantity with the available quantity. |
| | 82 | **6.** If sufficient stock exists, the operation continues. |
| | 83 | **7.** If insufficient stock exists, the trigger raises an exception and prevents the order from being created. |
| | 84 | |
| | 85 | COALESCE is used so that a store with no reviews receives a rating of 0 instead of NULL. |
| | 86 | |
| | 87 | === Reason for trigger |
| | 88 | |
| | 89 | This trigger is useful because: |
| | 90 | |
| | 91 | - It prevents customers from ordering unavailable products. |
| | 92 | - It protects the integrity of inventory data. |
| | 93 | - The validation is performed directly by the database. |
| | 94 | - The application cannot accidentally bypass the stock check. |
| | 95 | - It provides an immediate error when there is insufficient stock. |