2012-11-20 37 views
0

嗨,我有以下脚本ORACLE:比较两个瓦莱斯PL/SQL

CREATE OR REPLACE TRIGGER DOUBLE_BOOKINGS 
BEFORE INSERT OR UPDATE ON BOOKING_SESSION 
FOR EACH ROW 
DECLARE 
    session_date TIMESTAMP; 
    session_room NUMBER; 
BEGIN 
    SELECT start_session 
     INTO session_date --- EXISTING SESSION 
     FROM booking_session 
    WHERE bk_room = :NEW.bk_room; 
    IF session_date = :NEW.start_session THEN 
    RAISE_APPLICATION_ERROR 
    (-1000, 'Room is already booked'); 
    END IF; 
END; 
/

脚本是假设,以配合在同一个房间,并同日已经存在的预订的任何新订单(停止重复预订)

但是它无法正常工作。

SQL> INSERT INTO BOOKING_SESSION VALUES (45,TO_TIMESTAMP('18/03/2012 10:00', ' 
INSERT INTO BOOKING_SESSION VALUES (45,TO_TIMESTAMP('18/03/2012 10:00', 'DD/MM 
      * 
ERROR at line 1: 
ORA-04098: trigger 'U1146815.ROOM_BOOKED' is invalid and failed re-validation 

start_session是我保存预约的日期和时间,时间戳的数据库列名。 booking_session是保存预订的名称,bk_room是房间的号码。

因此在提交预订前,我试图将new预订日期与同一房间的旧预订日期相匹配,然后显示错误消息。

更新

新的错误,似乎正在返回太多行我该怎么办一次一个。

ERROR at line 1: 
ORA-01422: exact fetch returns more than requested number of rows 
ORA-06512: at "U1146815.DOUBLE_BOOKINGS", line 5 
ORA-04088: error during execution of trigger 'U1146815.DOUBLE_BOOKINGS' 

回答

0

你显然有其他触发的BOOKING_SESSION表称为ROOM_BOOKED。该触发器处于无效(未编译)状态。

如果你只是想防止重复bk_room/start_session值的记录,只需添加一个唯一约束表:

ALTER TABLE booking_session 
add CONSTRAINT my_constraint UNIQUE (bk_room, start_session); 

编辑:你的新的错误是因为你的多个记录在同一个bk_room值该表,这是预期的。但是,正如我上面所述,你不需要触发器来防止重复,只是一个唯一的约束。

+0

是b是一个好主意,但是我仍然需要创建一个触发器,因为我被要求。看来我需要创建一个游标来一次处理一行。 –

0

如果在代码中使用SELECT...INTO,那么select必须返回一行。在其他情况下,它会抛出NO_DATA_FOUND异常或TOO_MANY_ROWS(您的情况)。你可以捕获这些例外,但它可能会使代码不清楚。更好地使用光标查询您的记录。

试试这个

CREATE OR REPLACE TRIGGER DOUBLE_BOOKINGS 
BEFORE INSERT OR UPDATE ON BOOKING_SESSION 
FOR EACH ROW 
DECLARE 
    session_date TIMESTAMP; 
    session_room NUMBER; 
    CURSOR c_existing IS 
     SELECT start_session 
      FROM booking_session 
     WHERE bk_room = :NEW.bk_room and 
       session_date = :NEW.start_session; 
    dummy_session c_existing.start_session%TYPE; 
BEGIN 
    OPEN c_existing; 
    FETCH c_existing INTO dummy_session; 
    IF c_existing%FOUND THEN 
     CLOSE c_existing; 
     RAISE_APPLICATION_ERROR 
      (-1000, 'Room is already booked'); 
    END IF; 
    CLOSE c_existing; 
END; 

/