0

以下触发是停止重复预订房间并为预约提供替代房间。我在展示房间时遇到了问题。你能告诉我哪里出错了吗?

CREATE OR REPLACE TRIGGER CHECK_APPOINTMENT 
BEFORE INSERT OR UPDATE OF APP_DATE,C_NO,
RM_NO,APP_TIME ON APPOINTMENT
FOR EACH ROW

DECLARE

  CURSOR C_APP                   
  IS
  SELECT APP_DATE,C_NO,APP_TIME,RM_NO    
    FROM APPOINTMENT;

  V_APP_DATE APPOINTMENT.APP_DATE%TYPE;  
  V_APP_TIME APPOINTMENT.APP_TIME%TYPE;
  V_C_NO APPOINTMENT.C_NO%TYPE;
  V_RM_NO APPOINTMENT.RM_NO%TYPE;
  I_RM_NO APPOINTMENT.RM_NO%TYPE;
  RM_BKED_ERROR EXCEPTION;           

BEGIN
  OPEN C_APP;                    
  FETCH C_APP INTO V_APP_DATE,V_C_NO,V_APP_TIME,V_RM_NO; 

  IF :NEW.C_NO=V_C_NO           
 AND:NEW.RM_NO=V_RM_NO          
 AND:NEW.APP_DATE=V_APP_DATE         
 AND:NEW.APP_TIME=V_APP_TIME         
 THEN 
   RAISE RM_BKED_ERROR;      
 END IF;    

 SELECT R.RM_NO 
   INTO I_RM_NO
   FROM ROOM R,BRANCH B 
  WHERE R.RM_NO <> :NEW.RM_NO 
   AND B.BRN_NO = :NEW.BRN_NO
   AND B.BRN_NO=R.BRN_NO
 GROUP BY R.RM_NO;

EXCEPTION
  WHEN RM_BKED_ERROR THEN            
    Raise_Application_error (-20000, 'ROOM ALREADY BOOKED FOR AN APPOINTMENT.THE FOLLOWING ROOMS ARE AVAILABLE '||I_RM_NO); 
    CLOSE C_APP;
END;
 /
4

1 回答 1

4

这看起来不像是一个正确的方法,因为触发器在执行约束方面是出了的差。

我会采用以下方法之一:

  1. 将预约代码封装在一个过程中,该过程首先获得对任何表中的房间记录的排他锁。然后它可以检查预约表中的重叠记录,如果所需的时间段是空闲的,则插入并提交。返回一个代码以指示预订成功或不成功,如果不成功,可能还有其他可用房间的列表(并提交或回滚以释放房间桌锁)。由于房间不可用并不是一个意外情况,我不会为此使用异常处理。

  2. 创建一个单独的表,其中每个房间最小预订周期(例如 15 分钟)有一行,房间和间隔标识符具有唯一键。使用该密钥冲突来通知预订不成功,但与第一种方法类似,不要将异常传递回应用程序。

于 2012-11-29T13:34:52.790 回答