Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

SQL:gatilho para evitar que dados inválidos sejam inseridos em uma tabela


Uma instrução insert pode inserir várias linhas. Por exemplo.:
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;

Essas inserções ocorrem em ordem arbitrária, então você não pode realmente aceitar uma linha e não a outra. Em vez disso, você deve rejeitar toda a instrução de inserção. O mesmo vale para atualizações, é claro, se tal puder ser feito.

Da mesma forma, você escreveria um gatilho de instrução after onde você observa a nova situação na tabela.
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 a tabela for grande e você quiser ver apenas as linhas inseridas/atualizadas para que esse gatilho seja executado rapidamente, você terá que escrever um gatilho composto em que você se lembre de reservar IDs em uma matriz no nível da linha e veja apenas essas linhas no nível da instrução.