2012-12-10 67 views
0

我正在做一些課程工作,我應該創建一個觸發器,在創建訂單之前檢查庫存水平,以查看庫存中是否有足夠的產品來滿足訂單。問題是講師沒有正確地教導我們創建觸發器的語法,我的問題是我不知道如何告訴觸發器我正在檢查的stocktable中的哪個行/列。我需要加入表格嗎?SQL:觸發語法

這是我到目前爲止的代碼(我只是即興表演在這裏,它並不真正的工作,但我把它在這裏給你的是什麼,我想acchieve一個想法):

CREATE OR REPLACE TRIGGER stock_check 
BEFORE INSERT OR UPDATE OF product_quantity ON orderline 
FOR EACH ROW 
DECLARE 
Newtotal number; 
insufficient_stock exception; 
BEGIN 
IF(:NEW.product_quantity > product_stock.stock_quantity) then 
raise insufficient_stock; 
Else 
:new.product_stock.stock_quantity - product_quantity = newtotal 
Update stock_quantity 
Set product_quantity = newtotal 


END IF; 
exception 
when insufficient_stock then 
raise_application_error(-20604,'There is not enoguh stock available'); 
END; 
+0

您能否定義「不真正工作」更好?你有什麼錯誤嗎?這是不是在做你期望的?它在做什麼,你期望什麼? – Ben

+0

這全部記錄在手冊中 - 特別是關於「您正在使用哪一行」的問題):http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#CIHEHBEB –

+0

這 - http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm – Annjawn

回答

1

我想你需要的東西像下面這樣:

CREATE OR REPLACE TRIGGER stock_check 
    BEFORE INSERT ON orderline 
    FOR EACH ROW 
DECLARE 
    oldtotal NUMBER 
    newtotal NUMBER; 
    insufficient_stock EXCEPTION; 
BEGIN 
    SELECT stock_quantity INTO old_total 
    FROM product_stock 
    WHERE product_id = :new.product_id: 

    IF(:new.product_quantity > oldtotal) then 
    RAISE insufficient_stock; 
    ELSE 
    newtotal := oldtotal - :new.product_quantity;   
    UPDATE stock_quantity 
     SET product_quantity = newtotal 
    WHERE product_id = :new.product_id; 
    END IF; 
EXCEPTION 
    WHEN insufficient_stock THEN 
    RAISE_APPLICATION_ERROR(-20604,'There is not enoguh stock available'); 
END; 

您仍然需要添加一列用於某種PRODUCT_ID的。我沒處理UPDATE情況下...

1

例如:

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 

更新完成第一個故意創建一個鎖(好像兩會在曾經做過這個電話,你想要的第二爲了避免庫存低於0)。

+0

觸發器創建時沒有錯誤。但是,當我嘗試測試它時,出現以下錯誤:ORA-01422:精確提取返回的請求數多於 ORA-06512:在「CRYDNING.STOCK_CHECK」,第13行 ORA-04088:觸發器執行期間出錯'CRYDNING.STOCK_CHECK' –

+0

@CathrineRydning確保'product_stock'上的唯一/主鍵是我在我的示例中放入的'prod_id =:new.prod_id'如果不是,則調整觸發器代碼以引用1行。它必須更新多行(並且在返回子句中失敗) – DazzaL

+0

此密鑰是一個名爲prodstock_comp的組合鍵,由外鍵product_code和product_size組成。但如果我用prodstock_comp替代product_stock,觸發器會出現以下編譯錯誤:PLS-00049:壞綁定變量'NEW.PRODSTOCK_COMP' –