2017-10-20 17 views
0

請求書が支払われた場合、新しいBill Itemを "Bill_Item"テーブルに挿入できないようにするトリガーを作成しようとしています。請求表には、Paid_YN列とPosted_YN列があります。したがって、どの請求書に追加するかに応じて、支払または転記された場合はそれを否定します。私の更新と削除のセクションは、このコード内では動作しますが、 "挿入"セクションでは動作しません。助けてください!インデントの欠如のために私のお詫び、適切にコピーするコードを取得できませんでした。 私が間違っている場所を教えてください!それは私の論理ですか?私は、グーグルでエラーメッセージの検索を試みましたが、まだそれを理解することはできません!OracleトリガーBEFORE INSERTにデータが見つかりません

TABLES ::

CREATE TABLE Bill (
Bill_Number NUMBER (6,0) 
CONSTRAINT Bill_pk PRIMARY KEY 
CONSTRAINT Bill_Number_NN NOT NULL, 
Bill_Date DATE DEFAULT SYSDATE 
CONSTRAINT Bill_Date_NN NOT NULL, 
Waiter_Number NUMBER (5,0) 
CONSTRAINT Bill_Waiter_Number_FK REFERENCES Waiter (Waiter_Number) 
CONSTRAINT Bill_Waiter_Number_NN NOT NULL, 
Table_Number NUMBER (2,0) 
CONSTRAINT Bill_Table_Number_NN NOT NULL, 
Customer_Count NUMBER (2,0) DEFAULT 1 
CONSTRAINT Bill_Customer_Count_CK CHECK (Customer_Count > 0) 
CONSTRAINT Bill_Customer_Count_NL NULL, 
Paid_YN CHAR (1) DEFAULT 'N' 
CONSTRAINT Bill_Paid_YN_CK CHECK ((Paid_YN = 'Y') OR (Paid_YN = 'N')) 
CONSTRAINT Bill_Paid_YN_NN NOT NULL, 
Posted_YN CHAR (1) DEFAULT 'N' 
CONSTRAINT Bill_Posted_YN_CK CHECK ((Posted_YN = 'Y') OR (Posted_YN = 'N')) 
CONSTRAINT Bill_Posted_YN_NN NOT NULL, 
Bill_GST NUMBER (6,2) DEFAULT 0 
CONSTRAINT Bill_GST_CK CHECK (Bill_GST >= 0) 
CONSTRAINT Bill_GST_NN NOT NULL, 
Bill_Total NUMBER (8,2) DEFAULT 0 
CONSTRAINT Bill_Total_CK CHECK (Bill_Total >= 0) 
CONSTRAINT Bill_Total_NN NOT NULL 
); 

CREATE TABLE Bill_Item (
Bill_Number NUMBER (6,0) 
CONSTRAINT BItem_Bill_Number_FK REFERENCES Bill (Bill_Number) 
CONSTRAINT BItem_Bill_Number_NN NOT NULL, 
Menu_Item_Number NUMBER (5,0) 
CONSTRAINT BItem_Menu_Item_Number_FK REFERENCES Menu_Item (Menu_Item_Number) 
CONSTRAINT BItem_Menu_Item_Number_NN NOT NULL, 
Discount NUMBER (5,2) DEFAULT 0 
CONSTRAINT BItem_Discount_CK CHECK ((Discount >= 0) AND (Discount <= 100)) 
CONSTRAINT BItem_Discount_NL NULL, 
Quantity_Sold NUMBER (3,0) DEFAULT 1 
CONSTRAINT BItem_Quantity_Sold_CK CHECK (Quantity_Sold > 0) 
CONSTRAINT BItem_Quantity_Sold_NN NOT NULL, 
Selling_Price NUMBER (6,2) DEFAULT 0 
CONSTRAINT BItem_Selling_Price_CK CHECK (Selling_Price >= 0) 
CONSTRAINT BItem_Selling_Price_NN NOT NULL, 
CONSTRAINT Bill_Item_PK PRIMARY KEY (Bill_Number, Menu_Item_Number) 
); 

トリガー::

CREATE OR REPLACE TRIGGER TR_Q5 
BEFORE 
    UPDATE OR 
    INSERT OR 
    DELETE ON 
    BILL_ITEM 
    FOR EACH ROW 

DECLARE 
v_Paid_YN CHAR(1); 
v_Posted_YN CHAR(1); 

BEGIN 
    IF UPDATING THEN 
    SELECT Paid_YN, Posted_YN 
    INTO v_paid_YN, v_Posted_Yn 
    FROM Bill 
    WHERE Bill_Number = :OLD.Bill_Number; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20001, 'Cannot update the bill once its been paid!'); 
    END IF; 
    IF v_Posted_YN = 'Y' AND 
     v_Paid_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20002, 'Cannot update the bill once its been posted!'); 
    END IF; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'Y' THEN 
     RAISE_APPLICATION_ERROR(-20003, 'Cannot update the bill once its been paid and posted!'); 
    END IF; 
    ELSIF INSERTING THEN 
    SELECT Paid_YN, Posted_YN 
    INTO v_paid_YN, v_Posted_Yn 
    FROM Bill 
    WHERE Bill_Number = :OLD.Bill_Number; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20004, 'Cannot add to the bill once its been paid!'); 
    END IF; 
    IF v_Posted_YN = 'Y' AND 
     v_Paid_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20005, 'Cannot add to the bill once its been posted!'); 
    END IF; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'Y' THEN 
     RAISE_APPLICATION_ERROR(-20006, 'Cannot add to the bill once its been paid and posted!'); 
    END IF; 
    ELSIF DELETING THEN 
    SELECT Paid_YN, Posted_YN 
    INTO v_paid_YN, v_Posted_Yn 
    FROM Bill 
    WHERE Bill_Number = :OLD.Bill_Number; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20007, 'Cannot delete from the bill once its been paid!'); 
    END IF; 
    IF v_Posted_YN = 'Y' AND 
     v_Paid_YN = 'N' THEN 
     RAISE_APPLICATION_ERROR(-20008, 'Cannot delete from the bill once its been posted!'); 
    END IF; 
    IF v_Paid_YN = 'Y' AND 
     v_Posted_YN = 'Y' THEN 
     RAISE_APPLICATION_ERROR(-20009, 'Cannot delete from the bill once its been paid and posted!'); 
    END IF; 
END IF; 
END TR_Q5; 
/
SHOW ERRORS; 

この挿入戻っ:ここ

Insert Into Bill_Item 
    (Bill_Number, Menu_Item_Number, Discount, Quantity_Sold, Selling_Price) 
Values 
    (4945, 2, 0, 1, 1.03); 


Error starting at line : 234 in command - 
Insert Into Bill_Item 
    (Bill_Number, Menu_Item_Number, Discount, Quantity_Sold, Selling_Price) 
Values 
    (4945, 2, 0, 1, 1.03) 
Error report - 
SQL Error: ORA-01403: no data found 
ORA-06512: at "ORCL1_05.TR_Q5", line 24 
ORA-04088: error during execution of trigger 'ORCL1_05.TR_Q5' 
01403. 00000 - "no data found" 
*Cause: No data was found from the objects. 
*Action: There was no data from the objects which may be due to end of 
fetch. 
+1

挿入するとNEW.Bill_Numberを使用しないでください。 – stee1rat

+0

また、これが完全に新しいレコードである場合は、NO_DATA_FOUND例外をチェックする必要があります: 'EXCEPTION WHEN NO_DATA_FOUND' – stee1rat

答えて

2

があなたのブルマです:

ELSIF INSERTING THEN 
    SELECT Paid_YN, Posted_YN 
    INTO v_paid_YN, v_Posted_Yn 
    FROM Bill 
    WHERE Bill_Number = :OLD.Bill_Number; 

INSERT中に:old名前空間がnullです。これは完全に論理的です。レコードを挿入していますが、古いレコードは他にありますか?

だから、解決策は

ELSIF INSERTING THEN 
    SELECT Paid_YN, Posted_YN 
    INTO v_paid_YN, v_Posted_Yn 
    FROM Bill 
    WHERE Bill_Number = :NEW.Bill_Number; 

:old非常に簡単で更新し、削除する際に、それらの枝が動作する理由である、有効です。 (値が変更されているかどうかを確認する場合を除いて、UPDATING時の現在値 - :new - の値をテストするのが通常です)

+1

ありがとうございました!これは一度このように説明されました! – Chase

関連する問題