Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Fehler abfangen - Funktion richtig beenden

  1. #1
    dodo ist offline Neuer Benutzer
    Registriert seit
    10.01.2011
    Beiträge
    16

    Standard Fehler abfangen - Funktion richtig beenden

    Hallo,

    ich habe eine Funktion, die innerhalb einer Schleife so einige UPDATES auf bestehende Tabellen durchführt.

    CREATE OR REPLACE FUNCTION my_function () RETURNS INT AS
    $BODY$
    DECLARE
    [...]
    BEGIN
    FOR i IN 0..count LOOP
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    [...]
    END LOOP;
    RETURN 1 ;
    END
    $BODY$
    LANGUAGE 'plpgsql' ;

    Die Berechnungen dauern auf meinem Rechner so 3,5 Tage. Bei meinem letzten Durchlauf trat dann leider am Ende der Berechnungen ein von mir nicht abgefangener Fehler auf "ERROR: cannot EXECUTE a null querystring". Daduch dass die Funktion abgebrochen wurde, wurde KEINES der vorher in der Funktion gelaufenen updates realisiert :-((

    Da ich nicht weiss, ob ich jetzt wirklich alle Fehler abgefangen habe, meine Frage:

    (i)
    gibt es eine Möglichkeit, die Funktion ordnungsgemäß beenden zu lassen, auch wenn irgendein Fehler auftritt, damit die vorangegangenen UPDATES durchgeführt werden können?
    (ii)
    gibt es eine Möglichkeit der Funktion nach jedem Schleifendurchlauf zu sagen, dass die UPDATES auch ausgeführt werden sollen?

    Herzlichen Dank für Eure Hilfe,
    dodo

  2. #2
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von dodo Beitrag anzeigen
    Hallo,

    ich habe eine Funktion, die innerhalb einer Schleife so einige UPDATES auf bestehende Tabellen durchführt.

    CREATE OR REPLACE FUNCTION my_function () RETURNS INT AS
    $BODY$
    DECLARE
    [...]
    BEGIN
    FOR i IN 0..count LOOP
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    query_string := 'UPDATE [...]';
    EXECUTE query_string;
    [...]
    END LOOP;
    RETURN 1 ;
    END
    $BODY$
    LANGUAGE 'plpgsql' ;

    Die Berechnungen dauern auf meinem Rechner so 3,5 Tage. Bei meinem letzten Durchlauf trat dann leider am Ende der Berechnungen ein von mir nicht abgefangener Fehler auf "ERROR: cannot EXECUTE a null querystring". Daduch dass die Funktion abgebrochen wurde, wurde KEINES der vorher in der Funktion gelaufenen updates realisiert :-((

    Da ich nicht weiss, ob ich jetzt wirklich alle Fehler abgefangen habe, meine Frage:

    (i)
    gibt es eine Möglichkeit, die Funktion ordnungsgemäß beenden zu lassen, auch wenn irgendein Fehler auftritt, damit die vorangegangenen UPDATES durchgeführt werden können?
    (ii)
    gibt es eine Möglichkeit der Funktion nach jedem Schleifendurchlauf zu sagen, dass die UPDATES auch ausgeführt werden sollen?

    Herzlichen Dank für Eure Hilfe,
    dodo
    Zuerst einmal würde ich an Deiner Stelle versuchen, das zu optimieren. Gelten die Updates alle für dieselbe Tabelle?

    Zu Deiner Frage: nein, eine Funktion ist nach außen eine Transaktion, entweder alles oder nichts. Wenn das schon so umständlich ist und lange dauert, und dabei auch "Teilerfolge" im Sinne einzelner Updates akzeptabel sind, dann könntest Du aber eine Art Batch-Datei schreiben, wo die einzelnen Updates jeweils gefolgt von COMMIT drin stehen, und das dann via psql ausführen lassen.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  3. #3
    dodo ist offline Neuer Benutzer
    Registriert seit
    10.01.2011
    Beiträge
    16

    Standard

    Hallo,
    es sind 3 verschiedene Tabellen auf denen das update durchgeführt wird - eine davon ist eben riesig. Außerdem werden noch ein paar temp Tabellen benutzt.

    Die Idee mit der Batch-Datei hört sich gut an. Da ich keine Erfahrung damit habe, könntest Du mir ein Beispiel geben - wie muss das aussehen, wie baue ich die Schleife?

    Herzlichen Dank,
    dodo

  4. #4
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von dodo Beitrag anzeigen
    Hallo,
    es sind 3 verschiedene Tabellen auf denen das update durchgeführt wird - eine davon ist eben riesig. Außerdem werden noch ein paar temp Tabellen benutzt.

    Die Idee mit der Batch-Datei hört sich gut an. Da ich keine Erfahrung damit habe, könntest Du mir ein Beispiel geben - wie muss das aussehen, wie baue ich die Schleife?

    Herzlichen Dank,
    dodo
    Du schreibst eine Datei, die etwa so aussieht:

    Code:
    begin;
    update table1 ...
    commit;
    begin;
    update table2 ...
    commit;
    Dann rufst psql auf:

    Code:
    psql -f <Datei>
    Einfach, oder?

    Deine Befehle werden ja in einer Funktion generiert, wenn du diese so umschreibst, daß sie die Befehle so in der Form mit dem commits; liefert, kannst das auch so machen:


    Code:
     psql -t -c "select 'select version();'" | psql -f -
    (mal als Beispiel, musst halt Deine Funktion aufrufen und dessen Ausgabe an psql verfüttern.)



    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  5. #5
    dodo ist offline Neuer Benutzer
    Registriert seit
    10.01.2011
    Beiträge
    16

    Standard

    Super!
    reicht es also, wenn ich immer folgendes in meiner Funktion schreibe:

    EXECUTE 'Begin';
    EXECUTE query_string;
    EXECUTE 'Commit';

    oder muss ich Begin und Commit in den query_string integrieren?

    dodo

  6. #6
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von dodo Beitrag anzeigen
    Super!
    reicht es also, wenn ich immer folgendes in meiner Funktion schreibe:

    EXECUTE 'Begin';
    EXECUTE query_string;
    EXECUTE 'Commit';

    oder muss ich Begin und Commit in den query_string integrieren?

    dodo
    Nein. Innerhalb einer Funktion kannst Du kein COMMIT machen.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  7. #7
    dodo ist offline Neuer Benutzer
    Registriert seit
    10.01.2011
    Beiträge
    16

    Standard

    Wie bekomme ich dann die Schleife hin?

  8. #8
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von dodo Beitrag anzeigen
    Wie bekomme ich dann die Schleife hin?
    Du veränderst Deine Funktion so, daß sie als Resultat einen TEXT liefert, der all die auszuführenden Kommandos enthält. Das Resultat ist dann Deine Batch-Datei.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  9. #9
    ads
    ads ist offline Super-Moderator
    Registriert seit
    08.02.2006
    Ort
    MD
    Beiträge
    4.056

    Standard

    Mit einzelnen Commits wird das aber auch nicht schneller, eher im Gegenteil.
    Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören

    Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

    PostgreSQL Service & Support

  10. #10
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von ads Beitrag anzeigen
    Mit einzelnen Commits wird das aber auch nicht schneller, eher im Gegenteil.
    Andere Baustelle. Das Konstrukt mit einer Schleife solche UPDATE-Befehle auf eine große Tabelle zu ballern ist eh bedenkenswert. Da könnte es sich sicher lohnen, zu schauen, ob man das anders machen kann.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Antworten: 12
    Letzter Beitrag: 08.10.2010, 14:15
  2. Beenden des Wiederherstellungsmodus
    Von Jens im Forum Allgemeines
    Antworten: 8
    Letzter Beitrag: 10.11.2009, 23:29
  3. Alle Verbindungen beenden. C#
    Von MHA im Forum Programmierung
    Antworten: 6
    Letzter Beitrag: 02.10.2009, 17:11
  4. SQL-Statement syntaktisch richtig?
    Von drgoette im Forum SQL
    Antworten: 5
    Letzter Beitrag: 24.07.2009, 14:22
  5. Wo ist der Fehler in der Funktion?
    Von BoOnOdY im Forum Trigger und Funktionen
    Antworten: 12
    Letzter Beitrag: 21.08.2007, 16:02

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum