我如何解决Trigger和raise_error输出

时间:2012-11-29 13:16:41

标签: oracle plsql triggers

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

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;
 /

1 个答案:

答案 0 :(得分:4)

这看起来不是一种正确的方法,因为强制执行约束的触发器臭名昭着

我会采用以下方法之一:

  1. 将约会预订代码封装在一个程序中,该程序首先获取任何表中的房间记录的独占锁定。然后它可以检查约会表中的重叠记录,并插入并提交所需的时间是免费的。返回一个代码,表明预订成功或不成功,如果不成功,也可能是其他可用房间的列表(并提交或回滚以释放房间桌锁)。由于房间不可用不是意外情况,我不会为此使用异常处理。

  2. 创建一个单独的表,每个房间有一行-minimum_booking_period(例如15分钟),房间和区间标识符上有唯一的密钥。使用该密钥违规通知预订不成功,但与第一种方法类似,不要将异常传回给应用程序。