0

こんにちは私は次のスクリプトを持っています

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予約日を同じ部屋の古い予約日と一致させて、エラーメッセージを表示しようとしています。

アップデート

新しいエラー、返される行が多すぎるようです。一度に1つずつ実行するにはどうすればよいですか。

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'
4

2 に答える 2

0

テーブルで呼び出さROOM_BOOKEDれた別のトリガーがあるようです。BOOKING_SESSIONそして、そのトリガーは無効な (コンパイルされていない) 状態にあります。

重複した bk_room/start_session 値を持つレコードを単に防止したい場合は、テーブルに一意の制約を追加するだけです:

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

編集:あなたの新しいエラーは、テーブルに同じ bk_room 値を持つ複数のレコードがあるためです。これは予想されることです。ただし、上で述べたように、重複を防ぐためのトリガーは必要ありません。一意の制約だけが必要です。

于 2012-11-20T21:50:57.210 に答える
0

コードで使用する場合SELECT...INTO、select は正確に 1 行を返す必要があります。それ以外の場合は、 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;

/

于 2012-11-21T04:24:08.480 に答える