sql >> Base de Datos >  >> RDS >> Oracle

SQL:activador para evitar que se inserten datos no válidos en una tabla

Una declaración de inserción puede insertar varias filas. Por ejemplo:

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;

Estas inserciones ocurren en orden arbitrario, por lo que realmente no puede aceptar una fila y no la otra. En su lugar, debe rechazar toda la declaración de inserción. Lo mismo es cierto para las actualizaciones, por supuesto, si se pueden hacer.

En consecuencia, escribiría un disparador de declaración posterior donde observa la nueva situación en la tabla.

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 tabla es grande y desea ver las filas insertadas/actualizadas solo para que este activador se ejecute rápidamente, tendrá que escribir un activador compuesto en el que recuerde los ID de reserva en una matriz en el nivel de fila y solo mire estas filas a nivel de declaración.