Jack2711 Jack2711 - 8 months ago 53
SQL Question

PL SQL trigger doesn't work

I have written a Trigger which fires on the insert or update of the table bestellung and I want it to change certain things when inserting or updating a file in the table. What I want to change I think you can see from the code.

I am working with APEX right now and when I try to insert an Order he always throws me the Error the Table is right now being changed and that the trigger maybe doesn't see the changes.

create or replace trigger bestellschluss_iuar
after insert or update on bestellung
for each row
DECLARE
v_date2 DATE;
v_hour number;

BEGIN

select bestelldatum + 2 into v_date2 from bestellung where bestellid = :new.bestellid;
select EXTRACT(HOUR FROM TO_TIMESTAMP(SYSDATE))into v_hour FROM DUAL;

IF :NEW.zieldatum IS NULL THEN
IF v_hour > 17 THEN
UPDATE bestellung
SET zieldatum = bestelldatum + 3
WHERE bestellid = :NEW.bestellid;
ELSE
UPDATE bestellung -- bestellung means order
SET zieldatum = bestelldatum + 2 --and this means deliverydate = orderdate +2
WHERE bestellid = :NEW.bestellid;
END IF;
ELSIF v_date2 > :NEW.zieldatum THEN
raise_application_error(-22501, 'Bestellungen für dieses Datum nicht möglich da zu Kurze Lieferzeit');
ELSIF (v_date2 = :NEW.zieldatum) AND v_hour > 18 THEN
raise_application_error(-22502, 'Bestellungen um diese Uhrzeit für diesen Tag nicht mehr möglich');
END IF;
END;​
/

Answer Source

I would use a BEFORE INSERT OR UPDATE trigger instead of an AFTER trigger here. In a BEFORE trigger, you can access and change the values of the affected row before they get inserted or updated, by assigning to :NEW.columnname. This is sufficient for you, as you are only querying/updating data in the row that the trigger has fired for.

This also avoids the 'table XYZ is mutating; trigger/function may not see it' error, because we are no longer attempting to query or update the table during a trigger that updates it.

I've had a go at rewriting your trigger as a BEFORE trigger. Please note that I haven't tested that it works, other than creating a suitable table and verifying that the trigger compiles:

create or replace trigger bestellschluss_iubr
  before insert or update on bestellung
  for each row
DECLARE 
  v_date2 DATE;
  v_hour number;

BEGIN
  v_date2 := :NEW.bestelldatum + 2;
  v_hour := EXTRACT(HOUR FROM SYSTIMESTAMP);

  IF :NEW.zieldatum IS NULL THEN
    IF v_hour > 17 THEN
      :NEW.zieldatum := :NEW.bestelldatum + 3;
    ELSE
      :NEW.zieldatum := :NEW.bestelldatum + 2;
    END IF;
  ELSIF v_date2 > :NEW.zieldatum THEN
    raise_application_error(-22501, 'Bestellungen für dieses Datum nicht möglich da zu Kurze Lieferzeit');
  ELSIF (v_date2 = :NEW.zieldatum) AND v_hour > 18 THEN
    raise_application_error(-22502, 'Bestellungen um diese Uhrzeit für diesen Tag nicht mehr möglich');
  END IF;
END;
/
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download