2016-05-16 5 views
0

Ich versuche, Änderungen an einer DB2-Tabelle mit einem Lösch-und Update-Trigger zu protokollieren. Nehmen wir ein einfaches Beispiel an: Eine Person hat eine Adresse. Die Protokolltabelle sollte nicht nur Personendaten, sondern auch einige Werte aus der Adresstabelle enthalten.ON DELETE-Trigger - Join auf alten Werten

So sind die Tische PERSON (ID, Name) und Anschrift (PERSON_ID, STREET, ...)

Hier ist, was ich versucht einzurichten:

CREATE TRIGGER log_history 
AFTER UPDATE OR DELETE ON person 
REFERENCING OLD AS O 
FOR EACH ROW MODE DB2SQL 
BEGIN 
DECLARE street VARCHAR(150); 
SET street = (SELECT street from ADDRESS join person on ADDRESS.person_id=O.id); 
INSERT INTO LOG(id,name,street) VALUES(O.id, O.name, street); 
END 

Die Updates protokolliert werden perfekt. Ich sehe alle alten Werte in die Protokolltabelle eingefügt, einschließlich der Straße.

Bei DELETE-Operationen enthält die Protokollzeile nur die Werte der Tabelle PERSON, die Spalte STREET ist jedoch für gelöschte Zeilen NULL.

Ich habe auch versucht, mit einem Vor-Trigger, und ich habe versucht, mit einer einfachen Where-Klausel verbinden. Das Ergebnis ist immer das Gleiche.

Ich sollte möglicherweise erwähnen, dass es eine ON DELETE CASCADE FK gibt, die die ADRESSE löscht, wenn Sie eine PERSON löschen. Ich verstehe jedoch, dass das Löschen dieser abhängigen Tabelle (ADRESSE ) nach den Triggern geschieht ...

Ich verwende DB2 10.5 LUW auf einem Linux-Server (sollte nicht relevant sein, aber ...)

Also weiß jemand, wie man verknüpfte Werte aus einer anderen Tabelle als die, die das Löschen auslöst, abruft? Thx

+1

Ihr Verständnis scheint falsch zu sein. Der AFTER löst aus, "nachdem die Änderungen, die durch die tatsächliche Aktualisierung der Betreff-Tabelle verursacht wurden, auf die Datenbank angewendet werden" - ein Zitat aus [dem Handbuch] (http://www.ibm.com/support/knowledgecenter/SSEPGG_10.5.0/ com.ibm.db2.luw.sql.ref.doc/doc/r0000931.html? cp = SSEPGG_10.5.0% 2F2-12-7-105 & lang = de). Beachten Sie "die Datenbank" vs. "die Tabelle". Dies umfasst eindeutig kaskadierte Aktionen, die "durch die tatsächliche Aktualisierung der Betreff-Tabelle verursacht werden". – mustaccio

+0

mustaccio, wie ich schon sagte, habe ich auch einen BEFORE-Trigger mit dem gleichen Ergebnis versucht. Wenn ich richtig verstehe, schlagen Sie vor, ein "KEIN CASCADE VOR UPDATE ODER LÖSCHEN" zu versuchen. Ich werde es versuchen.Ich glaube, ich habe es auch versucht, hatte aber Schwierigkeiten, den Auslöser mit einer Nachricht zu versehen, die ich nicht wirklich verstanden habe. Ich werde Sie über meine Ergebnisse auf dem Laufenden halten. Danke für das Kommentieren –

+0

Es scheint die NO CASCADE BEFORE Option funktioniert. Jetzt habe ich ein anderes Problem: Ich verwende ein cleveres Persistenz-Framework in meinem Programm, das bestimmt, dass das Adressobjekt ebenfalls gelöscht werden muss. Wenn ich also mit der TRIGGER-Lösung gehen wollte, müsste ich mit dem Framework kämpfen Caching und Objekt-Mapping und so, und das klingt wie ein Kampf, in dem Sie nur verlieren können. –

Antwort

0

Wie von mustaccio vorgeschlagen, KEIN CASCADE VOR LÖSCHEN oder UPDATE wird es mir ermöglichen, verbundene Werte abzurufen, die von der gelöschten Zeile referenziert wurden. Leider kann ich dieser Route nicht folgen, da das Persistenz-Framework, das wir verwenden, "clever genug" ist, um Delete-Anweisungen für die Adresstabelle zu geben, bevor die Person gelöscht wird. Unsere O/R-Mappings zu ändern und dem Framework zusätzliche Tricks für diesen speziellen Logging-Zweck beizubringen, scheint ein riskantes Unterfangen zu sein. Es scheint, als wäre die Implementierung des Protokollierungsverhaltens auf der Programmseite komparativ und weniger riskant. Also entschied ich mich, den TRIGGER überhaupt nicht zu wählen.

Egal was, danke mustaccio für Ihren Kommentar und Zeiger.

0

Nur um diesen Thread zu vervollständigen: Programmgesteuert zu arbeiten, hat nicht wirklich funktioniert, weil wir dann die alten Werte auf der Anwendungsseite verfolgen müssen.

Also, was haben wir am Ende? Wir haben eine Stored Procedure geschrieben und diese jedes Mal aufgerufen, wenn die betreffenden Datensätze in der aktuellen (anwendungsseitigen) Transaktion geändert werden. Dies hat eine Reihe von Einschränkungen, die schlimmste (und glücklicherweise in unserem Fall handhabbar) ist, dass Sie daran denken müssen, diese gespeicherte Prozedur von Hand aufzurufen. Ein Trigger auf dem Tisch wäre viel sicherer gewesen ... oh mein Gott.