挿入ステートメントは、複数の行を挿入できます。例:
insert into booking(booking_start, booking_end, booking_room, guest_no)
select date '2019-11-01', date '2019-11-10', 4, 10 from dual
union all
select date '2019-11-08', date '2019-11-15', 4, 88 from dual;
これらの挿入は任意の順序で発生するため、実際には一方の行を受け入れて、もう一方の行を受け入れることはできません。代わりに、挿入ステートメント全体を拒否する必要があります。もちろん、更新が可能であれば、同じことが当てはまります。
したがって、テーブル内の新しい状況を確認するafterステートメントトリガーを記述します。
CREATE OR REPLACE TRIGGER trg_reject_invalid_bookings
AFTER INSERT OR UPDATE ON booking
DECLARE
v_count INTEGER;
BEGIN
SELECT count(*)
INTO v_count
FROM booking b1
WHERE EXISTS
(
SELECT *
FROM booking b2
WHERE b2.booking_id <> b1.booking_id
AND b2.booking_room = b1.booking_room
AND b2.booking_start < b1.booking_end
AND b2.booking_end > b1.booking_start
)
AND rownum = 1; -- it suffices to find one overlapping pair
IF v_count > 0 THEN
raise_application_error(-20000, 'Invalid booking');
END IF;
END trg_reject_invalid_bookings;
テーブルが大きく、このトリガーを高速に実行するために挿入/更新された行のみを確認する場合は、代わりに、行レベルで配列内の予約IDを記憶し、確認するだけの複合トリガーを作成する必要があります。これらの行はステートメントレベルです。