Oracle
 sql >> Database >  >> RDS >> Oracle

SQL:trigger per impedire l'inserimento di dati non validi in una tabella

Un'istruzione insert può inserire più righe. Es.:

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;

Questi inserimenti si verificano in ordine arbitrario, quindi non puoi davvero accettare una riga e non l'altra. Invece devi rifiutare l'intera dichiarazione di inserimento. Lo stesso vale ovviamente per gli aggiornamenti, se possibile.

Di conseguenza dovresti scrivere un trigger di istruzione dopo in cui guardi la nuova situazione nella tabella.

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;

Se la tabella è grande e vuoi guardare solo le righe inserite/aggiornate per fare in modo che questo trigger funzioni velocemente, dovresti invece scrivere un trigger composto in cui ricordi gli ID di prenotazione in un array a livello di riga e guarda solo queste righe a livello di istruzione.