Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Trigger ändert ganze Spalte statt nur geänderter Werte

Dieses Thema im Forum "Oracle" wurde erstellt von spinneimetz, 15 Januar 2017.

  1. spinneimetz

    spinneimetz Benutzer

    Hallo zusammen,

    ich bin neu im Forum und benötige etwas Hilfe beim Bearbeiten einer Datenbank. (Aufgabe fürs Studium).
    Bei uns ist es scheinbar üblich das man Aufgaben bekommt zu denen man noch nie etwas gelernt hat. Wir haben bisher eigentlich nur SELECT Anfragen geübt. Nun sollen wir aber eine komplette Datenbank erstellen und in Oracle Application Express darstellen. (Prüfungszulassung)

    Zum Verständnis haben wir jetzt ein paar Übungen bekommen.

    Nun hänge ich an folgender Aufgabe:
    Erzeugen sie im SQL-Developer einen Trigger CHANGE_LOCATION, der das Gehalt der Angestellten um 2% erhöht, wenn der Standort ihrer Abteilung verlegt wird.

    Das Gehalt ist SAL in der Tabelle EMP
    Die Abteilungsstandorte sind unter LOC in der Tabelle DEPT
    (sind glaube Standard Beispiel Dateien)

    Ich habe bisher (nach sehr langem suchen und lesen) folgendes Ergebnis:


    create or replace Trigger CHANGE_LOCATION
    AFTER UPDATE OF LOC
    ON DEPT
    FOR EACH ROW
    BEGIN
    UPDATE EMP
    SET sal=sal*1.02;
    end;

    Das Problem:
    Sobald ich einen Eintrag in LOC ändere, werden ALLE Einträge in SAL geändert. Nicht nur die entsprechenden.
    Ich habe viel mit WHEN Versucht und OLD. und NEW. aber komme einfach nicht weiter.

    Ich hoffe ihr könnt mir helfen.
    Leider verstehe ich auch den Grundaufbau und die einzelnen Befehle des Triggers noch nicht wirklich.

    Danke im Vorraus

    LG spinneimnetz
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Normal. Du führst ja letztendlich dies aus:

    Code:
    UPDATE EMP
    SET sal=sal*1.02;
    
    Du solltest diesem Update eine Where-Condition gönnen. Du kannst dabei auf NEW.* zugreifen. Du schaffst das!
     
  3. akretschmer

    akretschmer Datenbank-Guru

    Hast Dein Problem nun lösen können?
     
  4. drdimitri

    drdimitri Datenbank-Guru

    Psssst. Ist doch erst kurz nach 9 :D *duck renn und weg*
     
  5. spinneimetz

    spinneimetz Benutzer

    Ich arbeite noch dran. Saß gestern von Vormittags an und hab dann erstmal "FEIERABEND" gemacht. ;)
    Heute erstmal ein anderes Projekt und dann probiere ich weiter.
    Danke für den Hinweis erst einmal. Melde mich wieder!
     
  6. spinneimetz

    spinneimetz Benutzer

    Alsooo,
    Erst einmal hatte ich mich oben verschrieben.

    When habe ich zwar auch mal versucht aber hauptsächlich mit WHERE.

    Ich weiß aber nicht wie ich im sagen soll, das er nur die entsprechenden Zeilen ändern soll. Der Referenzschlüssel ist DEPTNO
    Habe es so versucht:
    WHERE DEPTNO=NEW.DEPTNO;
    aber denke mal das macht keinen Sinn oder? Die erste Änderung erfolgt ja in DEPT und die zweite in EMP. Also muss das ja irgendwie verglichen werden. :(

    Bekomme oft den Fehler:

    Fehler(8,16): PL/SQL: ORA-00904: "NEW"."DEPTNO": invalid identifier

    schreibe ich das richtig mit dem NEW.DEPTNO ?
     
  7. spinneimetz

    spinneimetz Benutzer

    aktueller Versuch

    create or replace Trigger CHANGE_LOCATION
    AFTER UPDATE OF LOC
    ON DEPT
    FOR EACH ROW
    BEGIN
    UPDATE EMP
    SET sal=sal*1.02
    WHERE DEPTNO=
    (SELECT DEPTNO
    FROM DEPT
    WHERE LOC=:NEW.LOC);
    end;

    Jetzt wird der Trigger an der seite zwar nicht mehr mit Fehlerkreuz angezeigt aber funktionieren tut er gar nicht mehr ;(

    Bzw. bekomme ich folgende Fehlermeldung wenn ich einen Standort ändere.

    Fehler beim Start in Zeile: 10 in Befehl -
    UPDATE DEPT
    SET LOC='NEW HAVEN'
    WHERE DEPTNO=20
    Fehlerbericht -
    ORA-04091: table DBG1603.DEPT is mutating, trigger/function may not see it
    ORA-06512: at "DBG1603.CHANGE_LOCATION", line 2
    ORA-04088: error during execution of trigger 'DBG1603.CHANGE_LOCATION'


    PS: Kann man Einträge auch Ändern im Forum? Wegen der Doppelposts jetzt.
     
  8. drdimitri

    drdimitri Datenbank-Guru

    Ok, jetzt die Auflösung:
    Before Update Trigger und dann die
    Code:
    :new.sal:= :old.sal*1.02
    Variable setzen.
    Du kannst in einem Row Level Trigger nicht auf die Tabelle ändern, damit würdest Du in die Transaktion hineinschauen und Daten sehen, die nach außen hin evtl. nie existieren.

    Habs leider auch übersehen... :oops:
     
  9. spinneimetz

    spinneimetz Benutzer

    Erst einmal danke für die Antwort.

    Leider verstehe ich es nicht ganz.
    Also ich ändere AFTER zu BEFORE und dann jetzt ohne das WHERE? Oder muss auch das FOR EACH ROW geändert werden?

    create or replace Trigger CHANGE_LOCATION
    BEFORE UPDATE OF LOC
    ON DEPT
    FOR EACH ROW
    BEGIN
    UPDATE EMP
    SET :new.sal:=: old.sal*1.02;
    end;

    Fehlermeldung: bad bind variable 'NEW.SAL' bzw. 'OLD.SAL'

    PS:Kennt ihr vielleicht eine gute Seite wo man so was nachlesen kann? Ich finde weder im Skript vom Prof. noch in seinem empfohlenen Buch etwas. Da werden Trigger nur mit einem kleinen Bsp erwähnt -.-'
     
  10. drdimitri

    drdimitri Datenbank-Guru

    Nein, ohne Update.
    Einfach nur die Zuweisung wie ich sie geschrieben hab.

    Im Prinzip ist ein Trigger ein PLSQL Programm, welches mit einer Tabelle und einer Aktion verknüpft ist.

    Wenn du dich für Plsql interessierst dann nimm Oracle PLSQL Programming von Steven Feuerstein, die Oracle DB allgemein bekommst von Tom Kyte mit Expert Oracle Database Achitecture oder auch mit Pro Oracle SQL mit Fokus auf SQL.
     
  11. spinneimetz

    spinneimetz Benutzer

    Tut mir leid das ich mich so dusselig anstelle.

    Habe jetzt:

    Code:
    create or replace Trigger CHANGE_LOCATION
    BEFORE UPDATE OF LOC
    ON DEPT
    FOR EACH ROW
    BEGIN
      SET :new.sal := :old.sal*1.02;
    END;

    aber immer noch Fehlermeldungen. Habe jetzt einiges noch probiert aber komme nicht weiter.

    Zu meiner Verteidigung, ich bin MATHEstudentin und will eigentlich nur durch diese Datenbanken Prüfung kommen, danach überlasse ich das gern weiter den Profis.
     
  12. drdimitri

    drdimitri Datenbank-Guru

    Das Abschreiben musst noch üben ;)
    Kein SET, einfach nur die Zuweisung so wie ich sie geschrieben hab.
     
  13. spinneimetz

    spinneimetz Benutzer

    Ohje,:oops:

    aber so

    Code:
    create or replace Trigger CHANGE_LOCATION
    BEFORE UPDATE OF LOC
    ON DEPT
    FOR EACH ROW
    BEGIN
      :new.sal:= :old.sal*1.02;
    END;
    ist immer noch "Bad Bind variable"
    :(

    Und ich dachte das SET steht wirklich für "setze" das und das auf dies und jenes. Oder ist das nur bei "=" also ohne ":"?
     
  14. drdimitri

    drdimitri Datenbank-Guru

    Keine Ahnung was Du da treibst:
    Code:
    SQL> CREATE TABLE DEPT (SAL NUMBER,LOC VARCHAR2(100));
    
    Tabelle wurde erstellt.
    
    SQL> CREATE OR REPLACE TRIGGER CHANGE_LOCATION
      2  BEFORE UPDATE OF LOC
      3  ON DEPT
      4  FOR EACH ROW
      5  BEGIN
      6    :NEW.SAL:= :OLD.SAL*1.02;
      7  END;
      8  /
    
    Trigger wurde erstellt.
    
    SQL> insert into dept values(100,'Hamburg');
    
    1 Zeile wurde erstellt.
    
    SQL> select * from dept;
    
           SAL LOC
    ---------- -------------------------------------------------
           100 Hamburg
    
    SQL> update dept set loc='München';
    
    1 Zeile wurde aktualisiert.
    
    SQL> select * from dept;
    
           SAL LOC
    ---------- -------------------------------------------------
           102 München
    
    SQL>commit;
     
  15. akretschmer

    akretschmer Datenbank-Guru

    @drdimitri : lies noch mal #1, es geht um 2 Tabellen, wenn sich in der einen was ändert soll der TRIGGER in der anderen auch was ändern. Ich denke mal, das hast Du übersehen. Ich könnte das flink in PostgreSQL demonstrieren, aber das würde dem Fragesteller nur mittelmäßig helfen, dafür aber bestmöglichst verwirren ;-)
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden