[Oracle/PL-SQL] Frage zu Insert-Trigger

Hallo Leute,

ich würde gerne folgendes erreichen:

Wenn ein Datensatz in eine Tabelle eingefügt wird und in der Tabelle Foreign Keys enthalten sind, dann prüfen ob der Datensatz in der referenzierten Tabelle enthalten ist, sonst dort einen Dummy-Datensatz einfügen.

Wenn in der Tabelle schon ein Datensatz mit gleichem Primärschlüssel vorhanden ist, ein Update statt einem Insert machen.

Ich würde das Ganze gerne über Trigger machen, keine Stored Procedure wenn möglich.

Mein erstere Gedanke war ein Instead-Of-Trigger, die läßt mich das Oracle aber nicht für Tabellen anlegen (nur so nebenbei, wofür dann, wenn nicht für Tabellen??), außerdem würde es vermutlich einen endlos rekursiven Insert-Trigger geben, wenn ich dann dort erst wieder ein Insert machen würde.

Der zweite Ansatz wäre das mit den Foreign Keys im Before-Insert-Trigger zu machen und das Update im After-Insert-Trigger. Dazu müßte ich aber im After-Insert-Trigger abfragen können ob während des Inserts ein Fehler aufgetreten ist.

Weiß jemand wie das geht oder gibts bessere Ideen wie ich sowas realisieren kann?

Grüße, Robert

Überdenke doch das ganze. Entweder man definiert referentielle Integritätsregeln, oder man läßt sie. Regeln zu definieren, um sie dann selbst mit neuen raffinierten Methoden zu umgehen, erinnert mich an die politische Praxis der letzten Jahre :smile:

Gruß

J.

Überdenke doch das ganze.

Wir haben uns in einem dreier-Team gestern einen halben Tag lang den Kopf darüber zerbrochen. :o)

Das Problem ist, dass die Datensätze über eine Middleware ankommen, und niemand die Reihenfolge der Datensätze garantieren kann, d. h. es kommt eventuell zuerst ein Datensatz der einen anderen Datensatz referenziert der aber noch gar nicht da ist.

Der Aufwand die Datensätze in die richtige Reihenfolge zu bringen bevor sie bei der Datenbank landen ist unverhältnissmässig gross, deswegen haben wir uns für diese Lösung entschieden.

Allerdings hast du recht, dass wir uns dann die Constraints gleich ganz sparen könnten.

-(

Wohl nochmal darüber schlafen …

Grüße, Robert

Hallo Robert,

vielleicht geht doch ein Ansatz über einen Instead-Of-Trigger…

Instead-Of-Triggers können nur für VIEWs angelegt werden, innerhalb des Triggers ist jede „Schweinerei“ erlaubt, auch die ärgerlichen mutating table- bzw. mutating contraint-Probleme tauchen i.allg. nicht auf (Trigger arbeitet ja auf einer VIEW und nicht auf einer TABLE).

Meine Idee: Benenne Deine Relation um und kreiere eine View mit dem ursprünglichen Namen Deiner Relation, die diese Relation identisch abbildet. SELECTS, etc. gehen dann über die View unmittelbar auf die Relation, Deiner middleware sollte das egal sein (außer sie liest das data dictionary). Für INSERTs, UPDATEs, DELETEs kannst Du jetzt einen Instead-Of-Trigger schreiben und alles machen, was das Herz begehrt oder die Not befiehlt.

Ein „Schweinetrick“ übelster Art - aber wirkungsvoll! Habe ich in ähnlicher Situation schon mal so gemacht - ob das in Deinem Umfeld funktioniert und welche Seiteneffekte noch auf Lauer liegen… ausprobieren…

ciao,
Bernhard

PS: José hat natürlich Recht, sowas macht man eigentlich nicht… Ich sag dann immer: Schiedsrichter lässt Vorteil gelten.

CREATE OR REPLACE TRIGGER emp_dept_trigger
BEFORE INSERT OR UPDATE OF DEPTNO ON EMP
FOR EACH ROW
DECLARE
v_dummy NUMBER;
BEGIN

SELECT count(*)
INTO v_dummy
FROM dept
WHERE deptno = :new.deptno;

IF v_dummy = 0 THEN
INSERT INTO dept
VALUES(:new.deptno, ‚DUMMY‘, ‚DUMMY‘);
END IF;

END;
/

Hinweis:
Das Ganze funktioniert erst seit Oracle 8i, da nun die Referentiellen Constraints verzoegert (deffered) d.h. nach dem letzten Rowtrigger geprueft werden.

Und noch etwas zu den INSTEAD-OF-Triggern:
Views ueber mehr als eine Tabelle oder mit Berechnungen lassen keine DML-Operationen zu. Diese koennen durch den Trigger aber auf die Basistabellen umgeleitet werden.

Gruss Janus