sql >> Databasteknik >  >> RDS >> Oracle

SQL:trigger för att förhindra att ogiltiga data infogas i en tabell

En insert-sats kan infoga flera rader. T.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;

Dessa insättningar sker i godtycklig ordning, så du kan inte riktigt acceptera en rad och inte den andra. Istället måste du avvisa hela infogningssatsen. Detsamma gäller naturligtvis för uppdateringar, om sådana kan göras.

Följaktligen skulle du skriva en after statement trigger där du tittar på den nya situationen i tabellen.

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;

Om tabellen är stor och du bara vill titta på infogade/uppdaterade rader för att denna trigger ska gå snabbt, måste du istället skriva en sammansatt trigger där du kommer ihåg boknings-ID:n i en array på radnivå och bara tittar på dessa rader på satsnivå.



  1. mysql_insert_id alternativ för postgresql

  2. Oracle Select * returnerar rader men Select count(1) returnerar 0

  3. Ta bort dubbletter av rader (ta inte bort alla dubbletter)

  4. Kapslade CASE-satser i MySQL