Ergebnis 1 bis 8 von 8

Thema: for ... loop mit execute command

  1. #1
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard for ... loop mit execute command

    Hallo,

    ich baue gerade eine Schleife, die auf verschiedene Tabellen angewendet werden soll:

    Code:
    declare
    	rq record;                  -- record for iteration through query
            sTable varchar;
            sPCon vachar;
    
    begin
    [...]
    for rq in select * from sTable where pcon = sPCon loop 
    
    [...]
    
    end loop;
    [...]
    end
    sTable ist hier eine Variable vom Typ varchar, die den Namen der Tabelle enthält, auf die die Schleife angewendet werden soll. Sie kann so aber nicht verarbeitet werden. An anderen Stellen musste ich solche Anweisungen in ein execute command stecken und es lief.

    Meine Frage ist, wie ich das am Beginn einer Schleife mache. Geht das auch mit execute?

    Alternativ hatte ich mir überlegt, dass select command vorher auszulösen und das Ergebnis in einen record zu schreiben. Aber der enthält ja dann nur einen einzelnen Datensatz. Bei der Abfrage kommen aber viele Datensätze raus, die dann in der Schleife verarbeitet werden.

    Vielen Dank

    Eremit

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

    Standard

    Zitat Zitat von eremit Beitrag anzeigen
    Hallo,

    ich baue gerade eine Schleife, die auf verschiedene Tabellen angewendet werden soll:

    Code:
    declare
    	rq record;                  -- record for iteration through query
            sTable varchar;
            sPCon vachar;
    
    begin
    [...]
    for rq in select * from sTable where pcon = sPCon loop 
    
    [...]
    
    end loop;
    [...]
    end
    sTable ist hier eine Variable vom Typ varchar, die den Namen der Tabelle enthält, auf die die Schleife angewendet werden soll. Sie kann so aber nicht verarbeitet werden. An anderen Stellen musste ich solche Anweisungen in ein execute command stecken und es lief.

    Meine Frage ist, wie ich das am Beginn einer Schleife mache. Geht das auch mit execute?

    Alternativ hatte ich mir überlegt, dass select command vorher auszulösen und das Ergebnis in einen record zu schreiben. Aber der enthält ja dann nur einen einzelnen Datensatz. Bei der Abfrage kommen aber viele Datensätze raus, die dann in der Schleife verarbeitet werden.

    Vielen Dank

    Eremit
    EXECUTE INTO ist Dein Freund, PostgreSQL: Documentation: Manuals: PostgreSQL 9.0: Basic Statements

    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
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard

    Meinst Du so?

    Code:
    for rq in execute 'select * from ' || sTable || ' where pcon = ' || sPCon || '' into rq loop
    execute into ist mir nicht unbekannt. Die Beispiele in der Dokumentation beziehen sich aber nicht auf ein execute innerhalb einer Schleifendeklaration.

    Eremit

  4. #4
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard

    hmm... würde es vielleicht helfen, die record Variable als Feld zu deklarieren
    rq record[]
    dann execute into
    und hinterher
    for each row in rq loop??
    Eremit

  5. #5
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard

    Ich glaube einen Weg gefunden zu haben, aber komme trotzdem nicht weiter. Meine Annahme ist, dass mir hier eine Cursor-Variable weiterhelfen könnte:

    Code:
    CREATE OR REPLACE FUNCTION fn_testarray(OUT nValue numeric, OUT sRemark varchar) RETURNS record AS
    $$declare
        rowData datatable%ROWTYPE;
        cData refcursor;
        sTable varchar;
        sPCon varchar;
    
    begin
        sTable := 'datatable';
        sPCon := 'UO2<2+>';
        open cData for execute 'select * from ' || sTable || ' where pcon = ''' || sPCon || '''';
        loop
            fetch cData into rowData;
            raise notice 'PCon: %, DataType: %, CalcMode: %, Value: %', rowData.pcon, rowData.datatype, rowData.calcmode, rowData.value;
        end loop;  
        close cData;
        nValue := 1.0;
        sRemark := NULL;
        return;
    end;$$
      LANGUAGE 'plpgsql';
    Bei dieser Abfrage dürften nur eine Handvoll an Datensätzen abfallen. Tatsächlich werden mit raise notice nur NULLen ausgegeben - und das ohne Ende. Die Schleife scheint nicht korrekt beendet zu werden.

    Dieses Beispiel habe ich aus der Dokumentation: PostgreSQL: Documentation: Manuals: PostgreSQL 8.2: Cursors

    Tips?

    Eremit

  6. #6
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard

    Wenn ich hinter das fetch command folgendes setze

    Code:
        if not found then 
            raise exception 'not found';
        end if;
    dann wird die exception ausgelöst. Also findet fetch einfach nichts, was aber nicht sein kann. Jedenfalls liefert die Abfrage, wenn ich sie so auf der Konsole abfeuere, ein paar Datensätze.

    Eremit

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

    Standard

    Zitat Zitat von eremit Beitrag anzeigen
    hmm... würde es vielleicht helfen, die record Variable als Feld zu deklarieren
    rq record[]
    dann execute into
    und hinterher
    for each row in rq loop??
    Eremit
    mal eine Demo:

    Code:
    test=# select * from foo;
     id | val
    ----+-----
      1 |   0
      3 |   0
      2 |   2
     20 |   1
    (4 rows)
    
    test=*# create or replace function eremit(t text) returns setof text as $$ declare r record; begin for r in execute 'select * from ' || $1 loop raise notice 'zeile'; end loop; end; $$ language plpgsql;
    CREATE FUNCTION
    test=*# select * from eremit('foo');
    NOTICE:  zeile
    NOTICE:  zeile
    NOTICE:  zeile
    NOTICE:  zeile
     eremit
    --------
    (0 rows)
    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

  8. #8
    eremit ist offline Benutzer
    Registriert seit
    19.02.2007
    Ort
    Braunschweig
    Beiträge
    49

    Standard

    Vielen Dank, genau so hat es funktioniert.
    Eremit

Ähnliche Themen

  1. invalid command \n bei DB-Restore
    Von Hannes23 im Forum Allgemeines
    Antworten: 1
    Letzter Beitrag: 13.07.2011, 16:18
  2. for i in loop returns setof int
    Von shans im Forum PL/pgSQL
    Antworten: 2
    Letzter Beitrag: 02.09.2009, 16:11
  3. Antworten: 2
    Letzter Beitrag: 25.11.2008, 10:55
  4. pg_ctl -> command not found
    Von killerniete im Forum Konfiguration
    Antworten: 9
    Letzter Beitrag: 07.02.2008, 18:50
  5. npgsql adapater batch command
    Von firealarm im Forum Programmierung
    Antworten: 0
    Letzter Beitrag: 31.10.2007, 16:15

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