2012-03-30 37 views
3

Der folgende Link in der PostgreSQL Dokumentation Handbuch http://www.postgresql.org/docs/8.3/interactive/populate.html besagt, dass Autocommit in PostgreSQL deaktivieren Sie können einfach alle einfügen Anweisungen in BEGIN; und COMMIT;Füllen einer Datenbank in PostgreSQL

Allerdings habe ich Schwierigkeiten bei der Erfassung von Ausnahmen, die zwischen dem Anfang auftreten können; VERPFLICHTEN; und wenn ein Fehler auftritt (wie das Einfügen einer doppelten PK), habe ich keine Möglichkeit, die ROLLBACK- oder COMMIT-Befehle explizit aufzurufen. Obwohl alle INSERT-Anweisungen automatisch zurückgesetzt werden, erwartet PostgreSQL immer noch einen expliziten Aufruf der COMMIT- oder ROLLBACK-Befehle, bevor die Transaktion als beendet betrachtet werden kann. Andernfalls muss das Skript auf einen Timeout der Transaktion warten, und alle danach ausgeführten Anweisungen führen zu einem Fehler.

In einer gespeicherten Prozedur können Sie die EXCEPTION-Klausel verwenden, dies gilt jedoch nicht in meinem Fall der Durchführung von Masseneinfügungen. Ich habe es versucht, und der Ausnahmeblock nicht für mich arbeiten, weil die nächste Anweisung/ausgeführt s, nachdem der Fehler erfolgt mit dem Fehler ausführen fehlschlägt:

ERROR: current transaction is aborted, commands ignored until end of transaction block 

Die Transaktion bleibt offen, da es nicht explizit abgeschlossen ist mit einem Aufruf von COMMIT oder ROLLBACK; Hier

ist ein Beispiel für den Code habe ich dies zu testen:

BEGIN; 
    SET search_path TO testing; 
    INSERT INTO friends (id, name) VALUES (1, 'asd'); 
    INSERT INTO friends (id, name) VALUES (2, 'abcd'); 
    INSERT INTO friends (id, nsame) VALUES (2, 'abcd'); /*note the deliberate mistake in attribute name and also the deliberately repeated pk value number 2*/ 
EXCEPTION /* this part does not work for me */ 
    WHEN OTHERS THEN 
     ROLLBACK; 
COMMIT; 

Wenn eine solche Technik muss ich garantieren wirklich, dass alle Aussagen erfolgreich sein wird? Warum ist das so? Gibt es keine Möglichkeit, Fehler zu erkennen und einen Rollback explizit aufzurufen?

Danke

Antwort

2

, wenn Sie es zwischen beginnen und sich verpflichten, tun dann wird alles automatisch zurück im Falle einer Ausnahme gerollt. Auszug aus der von Ihnen geposteten URL: "Ein zusätzlicher Vorteil aller Einfügungen in einer Transaktion besteht darin, dass das Einfügen aller Zeilen, die bis zu diesem Punkt eingefügt wurden, rückgängig gemacht wird, sodass Sie gewonnen haben nicht mit teilweise geladenen Daten stecken bleiben. "

+0

Alle Aussagen werden zurückgesetzt und das ist richtig; Die Transaktion wird jedoch nicht als abgeschlossen betrachtet und alle Anweisungen, die danach ausgeführt werden sollen, werden nicht ausgeführt, da der oben genannte Fehler bei jeder neuen Anweisung auftritt. – prince

+0

Was planen Sie zu erreichen? Wenn weitere Daten unabhängig von den vorherigen Fehlern eingefügt werden sollen, fügen Sie sie in einem anderen Begin-Commit-Block hinzu. – FooLman

0

Wenn ich Datenbanken initiiere, d. H. Eine Reihe von Tabellen/Ansichten/Funktionen/Trigger/etc. und/oder laden in den initialen daten, ich benutze immer psql und es ist Variables, um den fluss zu steuern. Ich habe immer hinzufügen:

\set ON_ERROR_STOP 

an der Spitze meiner Skripte, so, wenn ich eine Ausnahme treffen, wird psql abbrechen. Es sieht so aus, als könnte dies auch in Ihrem Fall helfen.

Und in Fällen, wenn ich eine Ausnahmebehandlung tun müssen, verwende ich anonymous code blocks wie folgt aus:

DO $$DECLARE _rec record; 
BEGIN 
FOR _rec IN SELECT * FROM schema WHERE schema_name != 'master' LOOP 
    EXECUTE 'DROP SCHEMA '||_rec.schema_name||' CASCADE'; 
END LOOP; 
EXCEPTION WHEN others THEN 
NULL; 
END;$$; 
DROP SCHEMA master CASCADE; 
Verwandte Themen