wenn ich eine laengere Transaktion laufen lasse und waehrend der Ausfuehrung in einer Query Fehler auftritt (z.B. eine Foreign Key violation), ist danach die Transaktion automatisch zurueckgesetzt und akzeptiert keine weiteren Kommandos mehr.
Die Fehlermeldung lautet:
“Error while executing the query;
ERROR: current transaction is aborted, commands ignored until end of transaction block”
Gibt es eine Moeglichkeit, dies zu umgehen, dass ich von Programmcode aus entscheiden kann ob der Fehler ignoriert/korrigiert werden kann und die Transaktion fortfahren soll oder der Fehler schwerwiegend ist und ein Rollback erfolgen muss?
Ich benutze die Windows version der postgreSQL datenbank und verbinde mich von einer VC++ 6.0 Applikation ueber ODBC.
naja in diesem Fall wuerde ich die Transaktion gerne weiterlaufen lassen um zu sehen was noch so fuer Fehler auftreten wuerden.
Es handelt sich um eine Funktion “Preview Import”, der dem Benutzer simuliert, was passieren wuerde wenn er eine Text/XML Datei importiert.
Am Ende der Simulation wuerde ich gerne einen Bericht mit allen Datenfehlern anzeigen und ein Rollback ausfuehren um die Datenbank in ihren Ursprungszustand zuruecksetzen.
Wenn ich immer nur den ersten Fehler anzeigen kann, werden sich die Benutzer darueber beschweren dass sie zu viele Iterationen benoetigen um alle Datenfehler aufzufinden.
Achso ob das über die Datenbanktransaktionen gelöst werden sollte, kann ich jetzt schlecht beurteilen.
In der Regel prüfen wir die Daten immer bevor wir sie speichern.
Durch einen vorhergehenden Fehler kann es u.U. zu diversen Folgefehlern kommen, weil ein Benötigter Datensatz fehlt. Der vielleicht nicht auftreten würde, wenn er funktioniert hätte. Somit hätten wir für den User viel zuviele Fehlermeldungen, die evtl. nur Folgefehler sind.
z.B.
1. speichern eines neuen Debitoren Nr. 4711
2. Speichern eines Rechnungskopfen mit Referenz auf die Debitornr 4711
3. Speichern der einzelnen Rechnungspositionen mit Referenz auf den Rechnungskopf
Im Falle eines Fehlers bei Punkt 1 hätte ich 100%ig einen Folgefehler auf Punkt 2 (weil der Debitor ja nicht vorhanden ist)
UND je einen Fehler für jede Position, weil auch der Kopf fehlt.
Das wären div. Fehlermeldungen, obwohl nur beim speichern des Debitoren etwas schiefgelaufen ist.
angenommen der Schritt 1 “Debitor anlegen” kann nicht ausgefuehrt werden, so haette ich gerne die Moeglichkeit innerhalb von C++ einen try {} catch {} block zu schreiben um den Fehler zu beheben und danach die Transaktion weiterlaufen zu lassen. Das kann ich aber nicht, weil die Datenbank nun keine Kommandos mehr akzeptiert.
[ das machen kommerzielle Datenbanken wie Sybase / MSSQL Server uebrigens nicht ]
Habe aber einen Workaround gefunden, einfach keine Fehler mehr machen. Ich rufe statt ExecuteSQL(…) einfach eine stored procedure auf die alle Fehler abfaengt und mir den Fehlercode zurueckliefert.
CREATE OR REPLACE FUNCTION exec_sql_keep_transaction(IN sql_to_execute “varchar”, OUT the_state “varchar”, OUT the_message text) AS
$BODY$
BEGIN
BEGIN
EXECUTE sql_to_execute;
EXCEPTION
WHEN data_exception or integrity_constraint_violation or triggered_data_change_violation THEN
the_state = SQLSTATE;
the_message = SQLERRM;
RETURN;
END;
Leider habe ich in der Doku gelesen, dass ein “Except” Block immer einen bedeutend hoeheren Overhead mit sich bringt, insofern waere eine Verhaltensaenderung doch wuenschenswert.
Wie fristo schon erwähnte, hat es seinen Sinn mit den Transaktionen.
Wie du weiter oben geschrieben hast, willst du eh am Ende ein Rollback machen. Ich weiß jetzt nicht so genau, ob das geht - aber kannst du nach einem Fehler nicht: diesen korrigieren, die Aktion wiederholen und dann weiter machen?
Wie gesagt, ich weiß nicht, ob du nach einem RollbackFlag noch weitere Aktionen auf der DB durchführen kannst, mit der einzigen Bedingung, daß keine Transaktion nicht mehr commitbar ist.
Ich weiß auch nicht, wie groß deine Transaktion ist. Evtl. könntest du ein Rollback machen, eine neue neue Transaktion beginnen und korrigiert nochmal von vorn anfangen?!
Ähm, das mit einem Datenbankabsturz kann ich nicht ganz nachvollziehen.
Wir haben in unserer Anwendung regelmäßig Transaktionen, die nicht durchgeführt werden können (Rollback). Diese sind aber weitestgehend abgefangen und laufen kontrolliert - deshalb kann aber weiterhin auf die Datenbank zugegriffen werden.