例えば:
SQL> create table product_stock (prod_id number, stock_quantity number);
Table created.
SQL> create table orderline (prod_id number, product_quantity number);
Table created.
SQL> insert into product_stock values (1, 1002);
1 row created.
SQL>
SQL> CREATE OR REPLACE TRIGGER stock_check
2 BEFORE INSERT OR UPDATE OF product_quantity ON orderline
3 FOR EACH ROW
4 DECLARE
5 v_stock_quantity product_stock.prod_id%type;
6 v_Newtotal number;
7 insufficient_stock exception;
8 BEGIN
9 if updating
10 then
11 v_Newtotal := :new.product_quantity - :old.product_quantity;
12 else
13 v_Newtotal := :new.product_quantity;
14 end if;
15
16 Update product_stock
17 Set stock_quantity = stock_quantity - v_Newtotal
18 where prod_id = :new.prod_id
19 returning stock_quantity into v_stock_quantity;
20
21 IF (v_stock_quantity < 0)
22 then
23 raise insufficient_stock;
24 END IF;
25 exception
26 when insufficient_stock then
27 raise_application_error(-20604,'There is not enoguh stock available');
28 END;
29 /
Trigger created.
SQL> show errors
No errors.
SQL> select * from product_stock;
PROD_ID STOCK_QUANTITY
---------- --------------
1 1002
SQL> insert into orderline values (1, 1000);
1 row created.
SQL> select * from product_stock;
PROD_ID STOCK_QUANTITY
---------- --------------
1 2
SQL> insert into orderline values (1, 3);
insert into orderline values (1, 3)
*
ERROR at line 1:
ORA-20604: There is not enough stock available
ORA-06512: at "DTD_TRADE.STOCK_CHECK", line 17
ORA-04088: error during execution of trigger 'DTD_TRADE.STOCK_CHECK'
SQL> select * from product_stock;
PROD_ID STOCK_QUANTITY
---------- --------------
1 2
意図的にロックを作成するために最初に update を実行します (2 つのセッションが一度にこの呼び出しを行った場合、在庫が 0 を下回るのを避けるために 2 番目のセッションをブロックする必要があるように)。