2016-07-25 5 views
1

Ich verwende pg-Versprechen, um meine SQL-Abfragen auszuführen. Die Abfragen selbst werden in externen .sql-Dateien gespeichert.PostgreSQL Catching Transaction Error und Rollback

Wenn ich eine Transaktion ausfühle, wird Postgres die Transaktion abbrechen, wenn ein Fehler auftritt (wie erwartet). Das Problem, auf das ich stoße, ist, dass separate Abfragen, die ich nach dem Abbruch der Transaktion ausführen möchte, nicht ausgeführt werden und stattdessen die folgende Nachricht angezeigt wird: "aktuelle Transaktion wird abgebrochen, Befehle werden bis zum Ende des Transaktionsblocks ignoriert". Wenn die Abfragen in der psql-Konsole ausgeführt würden, könnte ich dieses Problem lösen, indem ich nach der fehlgeschlagenen Abfrage ein ROLLBACK ausstelle. Ich denke nicht, dass dies eine Option ist, da das von meiner Anwendung verwendete SQL in einer externen Datei gespeichert ist. Ich denke auch nicht, dass Sicherungspunkte eine Option sind, da die gesamte Transaktion verworfen werden sollte, wenn etwas fehlschlägt.

Wie würde ich in der SQL-Datei einen Rollback durchführen, wenn dieser Fehler auftritt?

Hier ist die SQL-Referenz:

BEGIN; 

DELETE 
FROM tournament_tossup_values 
WHERE tournament_id = $1 AND 
NOT EXISTS 
(
    SELECT id 
    FROM tournament_match 
    WHERE tournament_id = $1 
); 

UPDATE tournament 
SET bonus_point_value = $5, parts_per_bonus = $6 
WHERE id = $1 AND NOT EXISTS (
    SELECT id 
    FROM tournament_match 
    WHERE tournament_id = $1 
) 
RETURNING bonus_point_value, parts_per_bonus; <-- Any subsequent accesses to the database by the application fail if this transaction fails 

COMMIT; <-- I want to rollback everything if this fails 

Vielen Dank im Voraus!

+0

Sie beziehen sich auf Bibliothek [pg-promise] (https://github.com/vitaly-t/pg-promise), aber Sie verwenden nicht die Unterstützung für Transaktionen - Methode 'tx'? In diesem Fall können wir nicht sicher sein, was vor sich geht, da Sie nicht den vollständigen Code dessen zeigen, was Sie tun. Vielleicht ist es am besten, dass Sie die Methode 'tx' verwenden und Abfragen ausführen, wie in allen Beispielen gezeigt. Siehe [Transaktionen] (https://github.com/vitaly-t/pg-promise#transactions). Dadurch wird Ihr Code berechenbarer, da Sie in Ihrem SQL sowieso keine richtige 'ROLLBACK'-Logik bereitstellen. –

Antwort

1

Wenn Sie eine Transaktion in einer externen SQL-Datei implementieren, müssen Sie die richtige Handhabung für COMMIT und ROLLBACK bereitstellen. Wenn Sie dies nicht tun, kann der Transaktionsstatus innerhalb Ihres serverseitigen Codes unvorhersehbar werden und zu dem Typ der Fehler führen, die Sie erhalten.

Dies kann ein bisschen schwierig sein, und einfacher gesagt als getan. Deshalb ist die beste Lösung, es überhaupt nicht zu tun.

Das Modul pg-promise, das Sie bereits verwenden, bietet eine zuverlässige Verarbeitung für Transaktionen über die Methode tx, die Sie verwenden sollten.

Zu diesem Zweck teilen Sie Ihre SQL-Datei in zwei Dateien - ein mit Ihrem DELETE Betrieb und ein mit Ihrem UPDATE Betrieb, und sie dann innerhalb einer Transaktion als zwei Abfragen ausführen:

db.tx(t => { 
    return t.batch([ 
     t.none('DELETE...'), 
     t.any('UPDATE...') 
    ]); 
}) 
    .then(data => { 
     // success; 
    }) 
    .catch(error => { 
     // error; 
    }); 
+0

Ah, diese Lösung ist, was ich näherte. Ich wollte nur sicherstellen, dass es keine Lösung gibt, mit der ich alles in einer SQL-Datei behalten könnte. Ich werde weitermachen und es so implementieren, wie Sie es oben beschrieben haben. Vielen Dank! :) – mbhuiyan

+0

@mbhuiyan kann eine einzige Datei eine Lösung sein, aber es wäre viel peinlicher zu implementieren und zu verwenden, nicht wirklich wert, wenn eine 'pg-Versprechen'-Transaktion ist so viel einfacher zu bedienen. –

Verwandte Themen