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. room-minimal_booking_period (例: 15 分) ごとに 1 つの行を持つ別のテーブルを作成し、部屋と間隔の識別子に一意のキーを付けます。そのキー違反を使用して、予約が成功しなかったことを通知しますが、最初のメソッドと同様に、アプリケーションに例外を返さないでください。

于 2012-11-29T13:34:52.790 に答える