Trigger ändert ganze Spalte statt nur geänderter Werte

spinneimetz

Benutzer
Beiträge
8
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
 
Werbung:
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!
 
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!
 
Alsooo,
Erst einmal hatte ich mich oben verschrieben.

Ich habe viel mit WHEN Versucht und OLD. und NEW.
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 ?
 
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.
 
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:
 
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 -.-'
 
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.
 
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.
 
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 ":"?
 
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;
 
Werbung:
@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 ;-)
 
Zurück
Oben