2014-12-10 130 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; 

这将导致异常被重新提升到调用代码任何现有的处理程序,这应该是足够聪明的回滚事务。

分享和享受。