Oracle Procedure Aufruf im Trigger
Moin zusammen,
ich habe ein kleines Problem, einen Datenbank Trigger zum laufen zu bekommen, und hoffe Ihr könnt mir hier helfen.
Ich habe eine Procedure geschrieben, welche ein Update auf eine Tabelle macht, und 2 Parameter benötigt.
Anbei mal die Procedure
Nun brauche ich einen Trigger, der jedesmal wenn auf eine bestimmte Tabelle ein Update oder Insert gemacht wird, der Trigger ausgelöst wird.
Aktuell sieht mein Trigger wie folgt aus:
Der Trigger wurde soweit auch erstellt.
Jedoch wenn ich einen Insert auf die Tabelle osq01_abflug mache, erhalte ich folgende Fehlermeldung:
Anbei auch mein Insert Befehl:
Hat jemand eine Idee wo hier mein Fehler liegt und kann mir helfen ?
Danke
Gruß
BadFsaadKl
ich habe ein kleines Problem, einen Datenbank Trigger zum laufen zu bekommen, und hoffe Ihr könnt mir hier helfen.
Ich habe eine Procedure geschrieben, welche ein Update auf eine Tabelle macht, und 2 Parameter benötigt.
Anbei mal die Procedure
create or replace
procedure add_flugstunden
(
p_per_nr in osq01_pilot.per_nr%TYPE,
p_bez in osq01_flug.f_bez%TYPE
)
is
BEGIN
declare
cursor cur_get_data
is
select
pil.p_std,
flg.zeit
from
osq01_pilot pil,
osq01_flug flg,
osq01_abflug aflg
where
aflg.f_bez = flg.f_bez and
aflg.per_nr = pil.per_nr and
aflg.f_bez = p_bez
;
v_p_std osq01_pilot.p_std%TYPE;
v_zeit osq01_flug.zeit%TYPE;
begin
open cur_get_data;
fetch cur_get_data into v_p_std, v_zeit;
update osq01_pilot
set p_std = v_p_std + v_zeit
where
per_nr = p_per_nr;
close cur_get_data;
end;
END add_flugstunden;
Nun brauche ich einen Trigger, der jedesmal wenn auf eine bestimmte Tabelle ein Update oder Insert gemacht wird, der Trigger ausgelöst wird.
Aktuell sieht mein Trigger wie folgt aus:
create or replace trigger tr_add_flugstunden
after insert or update on osq01_abflug
for each row
begin
add_flugstunden(:new.per_nr, :new.f_bez);
end tr_add_flugstunden;
/
Der Trigger wurde soweit auch erstellt.
Jedoch wenn ich einen Insert auf die Tabelle osq01_abflug mache, erhalte ich folgende Fehlermeldung:
Fehlerbericht:
SQL-Fehler: ORA-04091: table SGD.OSQ01_ABFLUG is mutating, trigger/function may not see it
ORA-06512: at "SGD.ADD_FLUGSTUNDEN", line 11
ORA-06512: at "SGD.ADD_FLUGSTUNDEN", line 28
ORA-06512: at "SGD.TR_ADD_FLUGSTUNDEN", line 2
ORA-04088: error during execution of trigger 'SGD.TR_ADD_FLUGSTUNDEN'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Anbei auch mein Insert Befehl:
INSERT INTO OSQ01_ABFLUG( F_BEZ, AB_DATUM, PER_NR, HERST, TYP, SER_NR, AB_ZEIT)
VALUES ('LH-341','14.11.06','10010001','Boeing','B737','ba23-0012','10,23')
Hat jemand eine Idee wo hier mein Fehler liegt und kann mir helfen ?
Danke
Gruß
BadFsaadKl
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 241844
Url: https://administrator.de/contentid/241844
Ausgedruckt am: 25.11.2024 um 20:11 Uhr
3 Kommentare
Neuester Kommentar
Moin BadFsaaKl,
soweit ich deine Tabellenstruktur verstehe, kannst du doch wirklich auf ein Lesen der "Abflug"-Tabelle verzichten, wie in der Fehlermeldung nahegelegt.
Deine procedure sollte auch so funktionieren:
...denn das bisher "joinende" Kriterium "aflg.f_bez = flg.f_bez and aflg.per_nr = pil.per_nr and aflg.f_bez = p_bez" läuft doch -ins Deutsche übersetzt- darauf hinaus, dass du jeweils genau einen Satz aus drei Tabellen liest und als Kreuzprodukt (1row*1*row*1row) dann eben auch genau einen Satz im Resultset erhältst.
Das geht auch als Kreuzprodukt aus zwei Tabellen.
Ich verstehe nicht, warum du einen Cursor verwendest... Trigger beziehen sich doch üblicherweise auf EINEN Datensatz, der INSERTed/UPDATEd oder DELETEd wird - so wie bei dir.
Trigger mit dem Scope "TABLE" gibt es auch - aber den brauchst du doch nicht in deinem Fall.
Ein Update oder Insert in der Abflug-Tabelle führt doch immer nur zu genau einem Folge-Update-Datensatz in der "Pilotstunden"-Tabelle - oder lese ich das falsch?
Grüße
Biber
soweit ich deine Tabellenstruktur verstehe, kannst du doch wirklich auf ein Lesen der "Abflug"-Tabelle verzichten, wie in der Fehlermeldung nahegelegt.
Deine procedure sollte auch so funktionieren:
create or replace
procedure add_flugstunden
(
p_per_nr in osq01_pilot.per_nr%TYPE,
p_bez in osq01_flug.f_bez%TYPE
)
is
BEGIN
declare
cursor cur_get_data
is
select
pil.p_std,
flg.zeit
from
osq01_pilot pil,
osq01_flug flg
where
pil.per_nr = p_per_nr
flg.f_bez = p_bez
;
v_p_std osq01_pilot.p_std%TYPE;
v_zeit osq01_flug.zeit%TYPE;
begin
open cur_get_data;
fetch cur_get_data into v_p_std, v_zeit;
update osq01_pilot
set p_std = v_p_std + v_zeit
where
per_nr = p_per_nr;
close cur_get_data;
end;
END add_flugstunden;
Das geht auch als Kreuzprodukt aus zwei Tabellen.
Ich verstehe nicht, warum du einen Cursor verwendest... Trigger beziehen sich doch üblicherweise auf EINEN Datensatz, der INSERTed/UPDATEd oder DELETEd wird - so wie bei dir.
Trigger mit dem Scope "TABLE" gibt es auch - aber den brauchst du doch nicht in deinem Fall.
Ein Update oder Insert in der Abflug-Tabelle führt doch immer nur zu genau einem Folge-Update-Datensatz in der "Pilotstunden"-Tabelle - oder lese ich das falsch?
Grüße
Biber
Moin BadFsaadKl,
na ja, sagen wir so - der Trigger bringt wohl keine Fehlermeldung mehr.
Allerdings würde ich noch mal in Ruhe darüber meditieren
a) ob du überhaupt einen Cursor brauchst, den du dann vollständig vom ersten bis zum ...ähmmm... ersten Satz durchfetchst - dafür würde auch ein einfaches direktes "UPDATE pilotentabelle" reichen IMHO.
b) und vor allem, ob denn wirklich bei jedem UPDATE in der abflug-Tabelle nochmal die Stunden in der Piloten-Tabellen addiert werden sollen.
Bei einem INSERT ja, durchaus.
Bei einem noch zu ergänzenden DELETE-Trigger auf der Abflug-Tabellen könnten ebenso blind wieder Stunden in der Pilotentabelle rausgerechnet werden.
Bei einem Update der Abflug-Tabelle, z.B weil jemand einen Tippfehler im Feld "Typ" von "Boeing 773" zu "Boeing 737" korrigiert - da kann es doch noch nicht sein, dass deswegen nochmals die Flugzeitstunden einem Piloten gutgeschieben werden.
Weil - die verdienen ohnehin schon genug.
Ich würde - schon zu Übungszwecken - nochmal
Grüße
Biber
na ja, sagen wir so - der Trigger bringt wohl keine Fehlermeldung mehr.
Allerdings würde ich noch mal in Ruhe darüber meditieren
a) ob du überhaupt einen Cursor brauchst, den du dann vollständig vom ersten bis zum ...ähmmm... ersten Satz durchfetchst - dafür würde auch ein einfaches direktes "UPDATE pilotentabelle" reichen IMHO.
b) und vor allem, ob denn wirklich bei jedem UPDATE in der abflug-Tabelle nochmal die Stunden in der Piloten-Tabellen addiert werden sollen.
Bei einem INSERT ja, durchaus.
Bei einem noch zu ergänzenden DELETE-Trigger auf der Abflug-Tabellen könnten ebenso blind wieder Stunden in der Pilotentabelle rausgerechnet werden.
Bei einem Update der Abflug-Tabelle, z.B weil jemand einen Tippfehler im Feld "Typ" von "Boeing 773" zu "Boeing 737" korrigiert - da kann es doch noch nicht sein, dass deswegen nochmals die Flugzeitstunden einem Piloten gutgeschieben werden.
Weil - die verdienen ohnehin schon genug.
Ich würde - schon zu Übungszwecken - nochmal
- einen UPDATE-Trigger schreiben (der nur bei einer Änderung der Felder "per_nr" und/oder "f_bez" feuert - denn in diesen Fällen müssen die bereits gebuchten Pilotenstunden reduziert werden und einem anderen Piloten gutgeschrieben werden)
- und den fehlenden DELETE-Trigger musst du ohnehin schreiben, es sei denn, ein Löschen eines Datensatzes der Abflug-Tabelle ist absolut ausgeschlossen.
Grüße
Biber