Oracle
 sql >> Datenbank >  >> RDS >> Oracle

SQL:Trigger, um zu verhindern, dass ungültige Daten in eine Tabelle eingefügt werden

Eine Einfügeanweisung kann mehrere Zeilen einfügen. Beispiel:

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;

Diese Einfügungen erfolgen in willkürlicher Reihenfolge, sodass Sie nicht wirklich eine Zeile akzeptieren können und die andere nicht. Stattdessen müssen Sie die gesamte Einfügeanweisung zurückweisen. Gleiches gilt natürlich auch für Updates, sofern solche vorgenommen werden können.

Dementsprechend würden Sie einen After-Statement-Trigger schreiben, in dem Sie sich die neue Situation in der Tabelle ansehen.

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;

Wenn die Tabelle groß ist und Sie nur eingefügte/aktualisierte Zeilen betrachten möchten, damit dieser Trigger schnell ausgeführt wird, müssen Sie stattdessen einen zusammengesetzten Trigger schreiben, bei dem Sie sich Buchungs-IDs in einem Array auf Zeilenebene merken und nur betrachten diese Zeilen auf Anweisungsebene.