Delete in Triggerfunktion, danach ein RAISE EXCEPTION

Hallo,

ich hab folgendes Problem und komm einfach nicht weiter.

Ich hab, unter anderem, 2 Tabellen welche durch eine 1:n- Beziehung miteinander verbunden sind. Also zB. Tabelle A(Master[1]) und B(Detail[n]). Weiterhin habe ich eine Prozedur, welche automatisch auch diese Tabellen mit Werten belegt. Nun zum Problem:

Ich teste mit einem Trigger Werte auf ihre Korrektheit in der Tabelle B. Stellt der Trigger fest das die Werte nicht korrekt sind, soll er den übergeordneten Wert in der Tabelle A löschen und danach eine EXCEPTION auslösen.

Also so:

EXECUTE ‘Delete from where <Primärschluessel A> =’ NEW.fremdschluesselB;
RAISE EXCEPTION ‘Constraint verletzt…’;

Die Triggerfunktion macht soweit alles was sie soll, die Exception wird geworfen, nur leider wird der wert in Tabelle A nicht gelöscht. Es kommt keinerlei Fehlermeldung. Ich kann den Wert dann ohne weiters von Hand löschen, was mir aber nix nützt.

Hat wer eine Idee was da das Problem sein könnte. Kommt die Exception irgendwie der EXECUTE zuvor? Ich bin für jede Idee dankbar!

Ich weiß nicht, welches Kraut Du geraucht hast, aber es war wohl nicht gut.

Lege die Tabellen einfach so an, daß B.fremdschlüssel auf A.primärschlüssel zeigt. Den Rest macht PG für Dich. Du bist hier nicht bei MySQL oder so, PG kann das von sich aus korrekt und besser als Du.

Falls ich dich wegens der 3 Bier, die ich grad intus habe, flasch geparst haben sollte: sorry und schildere Dein Problem noch mal so, daß man es auch unter leichtem Alk-Einfluß verstehen kann.

Andreas

Wie akretschmer schon schreibt, mach dir das Leben nicht unnötig kompliziert und nutze einfach einen Foreign Key. Der sorgt selbstständig dafür, das nur Werte eingetragen werden können, deren Fremdschlüssel vorhanden sind.

Um dir aber bei deinem Problem weiterzuhelfen: in dem Moment, in dem du die Exception auslöst, wird deine Transaktion ungültig. Alle deine Änderungen werden hier verworfen, also auch dein Delete. Hinterher ist die Tabelle wieder auf dem Stand von vorher, bevor die angefangen hast. Was ja eigentlich auch Sinn von Transaktionen ist: Bei einem Fehler (deine Exception ist ein Fehler) alles rückgängig machen und Anfangszustand wiederherstellen.

OK, nachdem man hier wahrscheinlich erstmal beleidigt werden muss bevor man ernst genommen wird versuche ich mich auch mal für die Leute verständlich zu machen welche 3 Bier intus haben :angry: .

Erst einmal, ich habe noch nix mit MySQL erledigt, kA wie, wo oder was da so abläuft. Ich habe bis jetzt hauptsächlich mit Oracle gearbeitet, logisch das man wenn man freie Alternativen sucht man wohl oder übel bei Postges landet. Des Weiteren war es auch nicht ganz meine Wahl sondern eher des Auftraggebers. Aber nun genug gerechtfertigt, für wen denn auch?

Kann sein das ich mich etwas undeutlich ausgedrückt hab, das geb ich zu. Ist eben immer schwer etwas so zu beschreiben das es verständlich wird. Nichtsdestotrotz hab ich mit einer ordentlichen Nachfrage nach weiteren Details gerechnet.

Ich wäre dankbar gewesen für jede hilfreiche Idee, nicht für triviale “Vorschläge” wie eine Fremdschlüsselbeziehung. Wenn mein “biertrinkender Freund” mal etwas genauer hinschauen würde, dann sähe er eine EINDEUTIGE Fremdschlüsselbeziehung zwischen Wert in Tabelle B (FK in B) und Tabelle A (PK in A), nämlich genau hier: ‘Delete from where <Primärschluessel A> =’ NEW.fremdschluesselB;. Logisch dann, das mein Problem anders gelagert sein muss. Mit ner ordentlichen Ansage das ich deutlicher werden soll, hätt ich mich sicher etwas genauer ausgedrückt. Ich dachte bis dato das ich ausreichend Info gegeben hätte. Vielleicht versuchst du es nüchtern nochmal!

ONTOPIC:

Da ich nicht mit Graßrauchen oä. beschäftigt war hab ich mir mal gedanken über mein Problem gemacht. Und bin auch auf die Ursache gekommen.

Man denke mal an das ACID- Prinzip. Wenn ich also innerhalb einer Transaction, was mit einem Trigger immer der Fall ist, eine Exception werfe, werden alle Aktionen rückgängig gemacht, also auch mein DELETE auf die andere Tabelle. Also muss ich anders vorgehen.

Jap, danke! Das Problem ist nicht die Beziehung zwischen Tabelle A und B, ich vergleiche Mit dem Trigger noch einen Wert aus einer Tabelle C mit einem Wert der Tabelle B. Stimmt der nicht überein, müssen die Werte der Tabelle B und A gelöscht werden, und danach MUSS ein Abbruch erfolgen, da die Werte von einer Prozedur eingefügt werden. Der Trigger realisiert sozusagen ein CHECK CONSTRAINT über 3 Tabellen. Naja, ich werd nun versuchen einfach um das Konstrukt ein BEGIN- COMMIT zu legen.

Aber THX nochmal, das war mal ein Ansatz wie ich ihn erwartet hätte

Hey,

  1. ich wollt weder Dich noch jemand anders beleidigen, okay?

  2. wenn du in einer plpgsql-funktion fehler abfangen willst, das schaue Dir das mal an:
    http://www.postgresql.org/docs/8.1/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING

  3. ich versteh dein Problem noch immer nicht wirklich. wenn du mit einem primary key in der einen und mit references auf diesen in der anderen tabelle arbeitest, dann überwacht PG die ref. Integrität, da bedarf es keiner extra Trigger oder so.

Ähm. Du fügst Werte in einer oder mehr Tabellen ein, aber es müssen diverse Bedingungen erfüllt sein, ansonsten darf nicht eingefügt werden und es ist eine exception zu werfen. Richtig so?

Dann würde ich das alles in einer function machen, der die Werte zu übergeben sind. Diese prüft und entscheidet dann, ob Insert oder RAISE EXCEPTION nötig ist. Aber mit einem BEGIN-COMMIT um Insert und Trigger etc. drum herum sollte es auch gehen.

Andreas

@Andreas

Ja, richtig so. War sicher anfangs auch etwas undeutlich beschrieben!

Ich weiß noch nicht so recht wie ich es machen werd. Ich habe nicht erwähnt das die besagte Prozedur in Access läuft (war nicht meine Idee, ich muss es nur umsetzen :frowning: ). Ich versuche jetzt erstmal herauszubekommen wie man in Access eine Transaction startet (was mir nicht so gefällt, weil ich gern alle Constraint- Funktionen in der DB hätte) oder und das ist wahrscheinlich besser, ich mach mir Gedanken wie ich das quasi- Check- Constraint über die 3 Tabellen anders realisieren kann.

Ja, wo ist das Problem?

create function test_and_insert(var1, var2, var3) returns bool ass $$…$$ language plpgsql;

Diese prüft und macht für Dich und gibt eine 1 oder true zurück wenn alles klappt oder wirft eine exception.

In Deinem, ähm, access würg, sorry, rufst Du dann nur noch select test_and_insert(‘foo’, ‘bar’, ‘fasel’) auf, fertsch.
Und schaust halt, was zurück kommt.

Ich werd es mal so versuchen. Ich hoffe das Access macht mit :wink: , dann, und da brauchst du dich nicht zu entschuldigen, das ist würg!!! Ich glaub ich bin noch nicht oft an solch Grenzen gestoßen wie im Access! Naja, wie gesagt, war nicht meine Idee…

Letztes Feedback für dieses Thema:

Ich hab mich jetzt für die Begin…Commit/Rollback- VAriante entschieden.

Gut an diesem Problem war, das ich noch diverse andere Problem mit aufdecken konnte, schlecht ist, das ich dadurch auch wieder ein Haufen arbeit bekommen hab :rolleyes: . Aber so isses nun mal…