2014-12-10 132 views
-1

我試圖編寫一個觸發器來檢查以確保條件滿足,然後才允許在乘客列表中預訂一個人。但是,如果條件不符合,我想禁止插入到乘客名單中。我的觸發器會觸發,但無論如何插入都會發生。我該如何解決這個問題?我做錯了什麼?在插入觸發器之前停止插入PL/SQL

例如

INSERT INTO passengerlist_my (flightID, personID, seatnumber) 
    VALUES (1, 5, '43B'); 

上面插入語句執行時它不符合的條件。人與PERSONID 5已經預定,但是當我運行的INSERT語句,它仍然插入

SET serveroutput ON 
    /
    CREATE OR REPLACE TRIGGER bookpersons 
    BEFORE INSERT ON passengerlist_my 
    FOR EACH ROW 
    DECLARE 
     --declaration section 
     checkflight number; 
     bookedseats number; 
     planecapacity number; 
     chkpbooked number; 

     FLIGHT_IS_FULL EXCEPTION; 
     PERSON_IS_BOOKED EXCEPTION; 
     querystr VARCHAR2(255) := 'INSERT INTO passengerlist_my (flightID, personID, seatnumber) 
            VALUES (:NEW.flightID, :NEW.personID, :NEW.seatnumber)'; 

    BEGIN 
     --check IF FLIGHT exists 
     SELECT COUNT(*) INTO checkflight FROM FLIGHT WHERE flightID = :NEW.flightID; 
     IF checkflight<1 THEN 
      RAISE_APPLICATION_ERROR(-2000, 'Flight doesnt Exist'); 
     END IF; 

     --check booked seats 
     SELECT COUNT(*) INTO bookedseats FROM passengerlist WHERE flightID = :NEW.flightID; 

     --check plane capacity 
     SELECT NUMBEROFSEATS INTO planecapacity FROM PLANETYPE 
     JOIN PLANE USING (PLANETYPEID) 
     JOIN FLIGHT USING (PLANEID) 
     WHERE flightID = :NEW.flightID; 

     --check if person is already booked 
     SELECT COUNT(*) INTO chkpbooked 
     FROM PASSENGERLIST_MY 
     WHERE FLIGHTID = :NEW.flightID AND personID = :NEW.personID; 
     IF chkpbooked>=1 THEN 
      RAISE PERSON_IS_BOOKED; 
     END IF; 

     IF bookedseats>=planecapacity THEN 
      RAISE FLIGHT_IS_FULL; 
     END IF; 

     INSERT INTO passengerlist_my (flightID, personID, seatnumber) 
     VALUES (:NEW.flightID, :NEW.personID, :NEW.seatnumber); 
     COMMIT; 


    EXCEPTION 
     WHEN FLIGHT_IS_FULL THEN 
     DBMS_OUTPUT.PUT_LINE('This flight is FULL. Passenger cannot be booked!'); 
     WHEN PERSON_IS_BOOKED THEN 
      DBMS_OUTPUT.PUT_LINE('Person is already booked!'); 
     WHEN OTHERS THEN 
     DBMS_OUTPUT.PUT_LINE('Error Occured. Passenger cannot be booked!'); 
    END; 
    /
+0

它仍然給你輸出線?我想如果你使用THROW或RAISERROR而不是RAISE,它應該可以工作。 – Skyl3lazer 2014-12-10 22:23:57

+0

是的,它會給出正確的輸出行,說明「該人已經被預訂」,但仍插入表中 – user3163416 2014-12-10 22:26:39

+0

您正在處理異常並且不會重新提升它,因此不會阻止插入。您也不需要觸發器代碼中的INSERT和COMMIT。 – 2014-12-10 22:32:28

回答

0

的問題是,你的異常處理程序是吃的異常,而不是再撫養他們。嘗試改變異常處理程序:

EXCEPTION 
    WHEN FLIGHT_IS_FULL THEN 
     DBMS_OUTPUT.PUT_LINE('This flight is FULL. Passenger cannot be booked!'); 
     RAISE; 

    WHEN PERSON_IS_BOOKED THEN 
     DBMS_OUTPUT.PUT_LINE('Person is already booked!'); 
     RAISE; 

    WHEN OTHERS THEN 
     DBMS_OUTPUT.PUT_LINE('Error Occured. Passenger cannot be booked!'); 
     RAISE; 

這將導致異常被重新提升到調用代碼任何現有的處理程序,這應該是足夠聰明的回滾事務。

分享和享受。