Penny: Trigger anlegen

Hallo,

diese Frage richtet sich an Leute mit Wissen über "Trigger" in
Datenbanken (hier die Oracle-Datenbank).

Die Eingabe des folgenden Triggers wird von der Oracle-Datenbank
mit einem Komplilierungs-Fehler quittiert - der Trigger wird
angelegt aber funktioniert nicht.
Der Fehler muß in den letzten 8 Zeilen des Triggers (ab dem
SELECT) liegen.

Vielleicht findet einer von Euch den Fehler.

Hinweis zum Verständnis:
Die Tabelle "sportlerin" enthält nur das Attribut "vereinsbeitrag"
und einen Fremdschlüssel "s_id", der auf den Primärschlüssel "m_id"
der Tabelle "mitglied" zeigt (in der alle übrigen Attribute einer
Sportlerin zu finden sind).

Hier der Trigger:

/*

* Trigger, der dafür sorgt, daß beim Einfügen von volljährigen SportlerInnen

* in die Tabelle "Sportlerin", der Vereinsbeitrag auf 20 Euro erhöht

* wird (Hinweis: SportlerInnen unter 18 zahlen nur 10 Euro).

*/

CREATE OR REPLACE TRIGGER beitrag

AFTER INSERT OR UPDATE ON sportlerin

FOR EACH ROW

DECLARE

geburt DATE;

BEGIN

SELECT m.geburtsdatum INTO geburt FROM mitglied m WHERE :new.s_id = m.m_id;

IF (MONTHS_BETWEEN(SYSDATE, geburt)/12>=18)

THEN

IF INSERTING OR UPDATING

THEN

UPDATE sportlerin SET vereinsbeitrag=20 WHERE s_id = :new.s_id;

END IF;

END;

/

  1. Hi Penny!

    Die Eingabe des folgenden Triggers wird von der Oracle-Datenbank
    mit einem Komplilierungs-Fehler quittiert

    Genauer?

    BEGIN

    (...)

    IF (MONTHS_BETWEEN(SYSDATE, geburt)/12>=18) THEN

    IF INSERTING OR UPDATING THEN

    UPDATE sportlerin SET vereinsbeitrag=20 WHERE s_id = :new.s_id;

    END IF;

    END;

    Da fehlt ein END IF.

    mfG
    Benjamin

    --
    Selfcode: ie:} fl:{ br:> va:) ls:< fo:( rl:? n4:# ss:| de:] js:| ch:? sh:( mo:? zu:)
    "Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung."
    (Albert Einstein)
    1. Hallo Benjamin,

      vielen Dank für Deinen Hinweis mit dem fehlenden END IF!
      Das war's!

      Viele Grüße!
      Penny

      Übrigens - die genaue Oracle-Ausgabe:
      Warning: Trigger created with compliation errors.

      1. Hallo Benjamin,

        Der Trigger ist leider doch noch fehlerhaft (s. Fehlermeldung unten).

        Hier nochmal der neue Trigger, der zwar ohne Feldermeldung angelegt
        werden kann, jedoch bei der Ausführung eine Fehlermeldung erzeugt
        und definitiv nicht funktioniert (z.B. setzt er nicht fehlerhafter Beträge
        auf 20 - wie im Trigger-Body gefordert

        Der Quellcode d. Triggers:

        /*
         * Trigger, der dafür sorgt, daß beim Einfügen von volljährigen SportlerInnen
         * in die Tabelle "Sportlerin", der Vereinsbeitrag auf 20 Euro erhöht
         * wird (Hinweis: SportlerInnen unter 18 zahlen nur 10 Euro).
         */
        CREATE OR REPLACE TRIGGER beitrag
        BEFORE INSERT OR UPDATE ON sportlerin
        FOR EACH ROW
        WHEN (NEW.vereinsbeitrag < 20)
        DECLARE
         geburt DATE;
        BEGIN
        SELECT m.geburtsdatum INTO geburt FROM mitglied m
                       WHERE :new.s_id = m.m_id;
        IF (MONTHS_BETWEEN(SYSDATE, geburt)/12>=18)
        THEN
         IF INSERTING OR UPDATING
         THEN
           UPDATE sportlerin SET vereinsbeitrag=20 WHERE s_id = :new.s_id;
         END IF;
        END IF;
        END;
        /

        Die Fehlermeldung dazu
        (der Trigger hat übrigens den Namen BEITRAG):

        UPDATE sportlerin SET vereinsbeitrag=10 where s_id=15;
                        *
        ERROR at line 1:
        ORA-04091: table LDB18.SPORTLERIN is mutating, trigger/function
        may not see it
        ORA-06512: at "LDB18.BEITRAG", line 9
        ORA-04088: error during execution of trigger 'LDB18.BEITRAG'

        Viele Grüße!
        Penny

        1. Hallo,

          bin mir nicht ganz sicher mit dem Mutating, aber

          CREATE OR REPLACE TRIGGER beitrag
          BEFORE INSERT OR UPDATE ON sportlerin

          ...UPDATE sportlerin SET vereinsbeitrag=20 WHERE s_id = :new.s_id;

          Das würde den Trigger nochmal auslösen??

          Vielleicht gibt es ja auch so etwas wie INSTEAD OF Trigger und vielleicht möchtest du den Trigger ja auch nur für INSERT auslösen und nicht auch für UPDATE.

          Ansonsten kannst du doch den Beitrag als Funktion in einem berechneten Feld darstellen, so quasi ganz ohne Trigger.

          Gruss, Frank

          1. Hallo Frank,

            ich glaube nicht, da der Trigger nur bei
            WHEN (NEW.vereinsbeitrag < 20)
            ausgelöst wird und ich update ihn ja auf = 20.

            Vielleicht ist dieses UPDATE in einem Trigger generell falsch ("mutating" vielleicht tatsächlich ein Hinweis darauf).

            Er meckert aber auch bei Zeile 9 und das ist
            IF (MONTHS_BETWEEN(SYSDATE, geburt)/12>=18)

            An einem von beiden wird's wohl liegen - ich blicke leider überhaupt nicht mehr durch.

            Ich kann Freitag erst ab 14.30 Uhr wieder weitertesten.

            Auf alle Fälle vielen Dank für Deinen Hinweis!

            Viele Grüße!
            Penny

            1. Hallo nochmal,

              na dann würd ich umsomehr empfehlen, auf den Trigger total zu verzichten und stattdessen einfach auf eine Funktion in einer View oder mithilfe einer Virtual Column (Oracle 11g), da brauchst du nicht ständig die Tabelle updaten und hast trotzdem bei jeden Aufruf die aktuellen Daten.

              Gruss, Frank