Oracle
 sql >> Base de données >  >> RDS >> Oracle

SQL :déclencheur pour empêcher l'insertion de données invalides dans une table

Une instruction d'insertion peut insérer plusieurs lignes. Ex. :

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;

Ces insertions se produisent dans un ordre arbitraire, vous ne pouvez donc pas vraiment accepter une ligne et pas l'autre. Au lieu de cela, vous devez rejeter l'intégralité de l'instruction insert. Il en va de même pour les mises à jour bien sûr, si cela peut être fait.

En conséquence, vous écririez un déclencheur d'instruction après où vous examineriez la nouvelle situation dans le tableau.

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;

Si la table est volumineuse et que vous souhaitez uniquement consulter les lignes insérées/mises à jour afin que ce déclencheur s'exécute rapidement, vous devez écrire un déclencheur composé à la place, dans lequel vous vous souvenez de la réservation des ID dans un tableau au niveau de la ligne et ne regardez que ces lignes au niveau de l'instruction.