PL/SQL Update in Stored Procedure updated alle Werte

triggerinside

Grünschnabel
Hallo liebe Forumsgemeinde,

ich grüble jetzt schon ewig daran, wie ich das Update hinbekomme.
Die Stored Procedure wird zwar ausgeführt, jedoch nicht so wie ich es mir vorstelle.

Problem:
Alle Datensätze werden mit den gleichen Werten aktualisiert, obwohl ich zwei Parametervariablen habe, die ich mit dem execute-befehl befülle. Aktualisiert soll natürlich nur der Datensatz werden, der den Parameter entspricht (ist immer nur einer).

SQL:
create or replace procedure add_flugstunden(
p_per_nr in pilot.per_nr%type,
ff_bez in flug.f_bez%type)
is
begin
UPDATE pilot set p_std = (
select
pi.p_std + fl.zeit
from
pilot pi,
abflug ab,
flug fl
where ab.per_nr = p_per_nr
and ab.f_bez = ff_bez
and ab.per_nr = pi.per_nr
and ab.f_bez = fl.f_bez
);
end add_flugstunden;
/

Besten Dank schonmal
Euer Triggerinside
 
Moin Triggerinside,

Die Tabelle pilot, auf die sich das Update bezieht, braucht noch eine WHERE-Bedingung.
Ist in diesem Fall trivial. Nämlich
WHERE per_Nr =p_per_Nr

Grüße
Biber
 
Hallo Biber,

irgendwie stehe ich auf dem Schlauch. Wo genau (in welcher Zeile) muss es denn eingefügt werden?
Ich habe deinen Teil in die Where-Klausel eingefügt.
Leider wird das Update noch immer auf alle Datensätze angewendet.

SQL:
CREATE OR REPLACE PROCEDURE add_flugstunden(
p_per_nr IN pilot.per_nr%TYPE,
ff_bez IN flug.f_bez%TYPE)
IS
BEGIN
UPDATE pilot SET p_std = (
SELECT
pi.p_std + fl.zeit
FROM
pilot pi,
abflug ab,
flug fl
WHERE
pi.per_Nr = p_per_Nr
and ab.per_nr = p_per_nr
AND ab.f_bez = ff_bez
AND ab.per_nr = pi.per_nr
AND ab.f_bez = fl.f_bez
);
END add_flugstunden;
/


Danke schonmal
 
Moin triggerinside,

so wie unten skizzieet war die Anpassung gemeint... das WHERE bezieht sich auf die Tabelle pilot und ist nicht Teil der WHERE-Bedingung zur Ermittlung der Flugstunden für das SET.

SQL:
CREATE OR REPLACE PROCEDURE add_flugstunden(
      p_per_nr IN pilot.per_nr%TYPE,
      ff_bez   IN flug.f_bez%TYPE  )
   IS
BEGIN
     UPDATE pilot pi
     SET pi.p_std = pi.p_std +
     ( SELECT
          fl.zeit
       FROM
          abflug ab,
          flug fl
       WHERE ab.per_nr = p_per_nr
         AND ab.f_bez = ff_bez
         AND ab.f_bez = fl.f_bez
         )
      WHERE
           pi.per_Nr = p_per_Nr
       ;
END add_flugstunden;
/

Sollte funktional gleichwertig sein mit deiner StP.

Anmerkung:
Ich halte allerdings den ganzen Plan, diese Flugstunden-je-Pilot redundant zu speichern für Dönekens.
Erstens kannst du sie jederzeit live berechnen und zweitens brauchst du ja auch noch mal einen Trigger/eine StP für die Aktualisierung bei Update oder Delete von Flug/Abflug-Daten.
Denn die StP oben behandelt nur den Fall "Neue Daten/INSERT" .

Grüße
Biber
 
Zuletzt bearbeitet:
Hallo Biber,

vielen lieben Dank für Deine Antwort - das passt soweit. Allerdings benötige ich jetzt noch einen Trigger, wie Du schon richtig vermutet hast.

Der möchte mir leider auch nicht so recht gelingen -> hier mein Versuch:

Code:
create or replace trigger trigger1
after insert or update or delete of p_per on abflug
begin
add_flugstunden;
end trigger1;
/

Der Trigger soll bei einem einfachen Update, Delete, Insert auf Tabelle Abflug, Feld p_per ausgeführt werden.

Besten Dank schonmal für die tolle Unterstützung
 
Na ja, triggerinside,

ganz so einfach werde ich es dir nicht machen... beim handwerklichen Teil unterstütze ich ja gerne.
Lieber wäre es mir schon, wenn ich dich doch dazu bringen könnte, diese redundante Datenspeicherung zu unterlassen.

Sei's drum, was immer du dir davon versprichst, diese Flugstunden-pro-Pilot irgendwo im Hintergrung zusammenzuharken: es wird dich schon ein bisschen Hirnschmalz kosten.
Denn die UseCases musst du schon klarer beschreiben, die gehen immer auf Kappe des Auftraggebers. ;)

Also, nehmen wir wirklich mal an, in diesem Triggergerüst würdest du eine Function oder Procedure "Add_Flugstunden" aufrufen wie oben skizziert mit zwei Parametern p_per="Pilot" und f_bez="FlugBezeichnung".

Der Trigger soll feuern bei INSERT, UPDATE oder DELETE des Feldes Abflug.P_PER

Was wären denn dann die "richtigen" Parameter, um die Pilotenstunden in Table "Pilot" zu korrigieren?
Zur Auswahl hast du ja im Trigger immer die :new- und :eek:ld-Pseudo-Spalten, also die neuen und alten Spaltenwerte.
Die kennst der Trigger.
Code:
Fall INSERT: Jemand fügt einen kompletten neuen Datensatz ein
:new.p_per="Pilot A"  :new_f_bez="ABC123"
:old_p_per =NULL      :old.f_bez = NULL)


Fall Update, nur Feld p_per
:new.p_per="Pilot A"  :new.f_bez="ABC123"
:old_p_per ="Pilot B"  : old.f_bez = "ABC123"

Fall DELETE:
:new.p_per=NULL  :new.f_bez=NULL)
:old_p_per ="Pilot B"  : old.f_bez = "ABC123"

Fall INSERT/DELETE sind ja noch überschaubar, aber beim Update musst du ja schon überlegen, was du in der "Pilotentabelle" alles aktualisieren willst.
Pilot A hat offensichtlich einen Flug mehr als vor dem Update in Tabelle Abflug. Okay.
Aber Pilot B hat doch auch einen Flug weniger als vor dem Update - der muss auch korrigiert werden.

Außerdem: du reagierst im Trigger nur auf Änderung von P_PER. Wenn sich aber der Pilot nicht ändert, sondern die Flugbezeichnung von "ABC123" ... meinetwegen auf "BRX456".
Was soll dann geändert werden bzw passieren in der Pilotentabelle?

Was ist mit einem Trigger für die Tabelle FLUG? oder kann es da keine relevanten Änderungen (=Auswirkunken auf Pilotenstunden) geben?


Schau bitte erstmal, ob du es mit Triggern überhaupt einfangen bzw. abfackeln kannst, also so, dass es auch konsistent bleibt.
Es besteht das Risiko, dass du relativ schnell in der Plioten-Tabelle eine andere Anzahl Flugstunden stehen hast als die Summe aller Flugstunden laut Tabelle Flug, Feld Flugzeit.

Aber wenn du der Meinung bist, du hast für alle UseCases eine Vorstellung, was der Trigger tun soll, dann können wir es handwerklich weitertreiben.

Grüße
Biber
Edit: ich musste oben Codetags nachtragen.
Darf sonst nicht "old" mit Doppelpunkt davor bzw new mit Doppelpunkt davor schreiben.
 
Zurück