Sebastian: PHP und CURSOR mit PostreSQL

Hi,

ich habe ein Script, welches eine große Datenmenge aus einem SELECT * FROM verarbeiten muss. Aus Neugier wollte ich mir dahingehend mal die PostgreSQL-Cursor ansehen. So siehts im Moment aus:
<?
$result = pg_query($conn, "SELECT count(*) FROM log_entries WHERE request_time BETWEEN '$t1' AND '$t2' LIMIT 3");

$nOfRecords=pg_fetch_row($result);
$nOfRecords=3; // zu Testzwecken!

$dbQuery = "SELECT * FROM log_entries WHERE request_time BETWEEN '$t1' AND '$t2' ORDER BY request_time DESC LIMIT 3;";

$result = pg_query($conn, $dbQuery);

$r = pg_query($conn, 'BEGIN;');
$r = pg_query($conn, 'DECLARE getRecords CURSOR FOR '. $dbQuery);
#$r = pg_query($conn, 'OPEN getRecords FOR ' . $dbQuery);
for ($i=0; $i< $nOfRecords; $i++) {
  $r   = pg_query($conn, "FETCH getRecords;");
  print_r($row);

}
$r = pg_query('CLOSE getRecords;');
$r = pg_query('COMMIT;');
?>

Allerdings funktioniert das nicht, d.h. es wird keine Fehlermeldung ausgegeben, es werden aber auch keine Daten angezeigt. Wo liegt der Hund begraben?

TIA,
Sebastian

  1. Hallo!

    ich habe ein Script, [...]

    Für das, was Du in Deinem Beispielscript vor hast, benötigst Du kein CURSOR.

    for ($i=0; $i< $nOfRecords; $i++) {
      $r   = pg_query($conn, "FETCH getRecords;");
      print_r($row);

    }

    pg_fetch_* recht da völlig aus.

    Der Unterschied zwischen einem LIMIT und CURSOR ist der, dass bei einem LIMIT die Anfrage für PostgreSQL erledigt ist. Bei einem CURSOR kannst Du in der Ergebnismenge hin und her wandern.

    BEGIN;
    DECLARE test CURSOR FOR SELECT spalten FROM tabelle; */
    FETCH 100 FROM test; /* die ersten 100 Datensätze (1-100) */
    FETCH 100 FROM test; /* die nächsten 100 Datensätze (101-200) */
    FETCH -50 FROM test; /* die letzten 50 Datensätze (151-200) */
    MOVE 2000 IN test;   /* Cursor auf Position 2000 setzen */
    FETCH 100 FROM test; /* die nächsten 100 Datensätze (2000-2100) */
    CLOSE test;
    COMMIT;

    André Laugks

    --
    Die Frau geht, die Hilti bleibt!
    1. Hi André,

      danke für deine Antwort!

      Würde trotzdem gerne mit den Cursorn rumspielen, rein interessehalber. Wo liegt denn mein Fehler?

      for ($i=0; $i< $nOfRecords; $i++) {
        $r   = pg_query($conn, "FETCH getRecords;");

      Hier steht natürlich noch:

      $row = pg_fetch_array($r);

      print_r($row);

      Das LIMIT 3 ist übrigens auch nur zu Testzwecken!

      Liebe Grüße
      Sebastian

      1. Hallo!

        Würde trotzdem gerne mit den Cursorn rumspielen, rein interessehalber. Wo liegt denn mein Fehler?

        Sollst Du auch, ich möchte Dich gar nicht dran hindern.

        Wo liegt denn mein Fehler?

          
        // getestet!!!  
          
        $conn = pg_connect("host=servername dbname=datenbankname user=username password=passwort");  
          
        // Hier habe ich Dein SQL-Statement rein kopiert.  
        // Sollte es nun immer noch nicht funktionieren,  
        // liegt es an Deinem SQL-Statement.  
        $dbQuery = "SELECT * FROM log_entries WHERE request_time BETWEEN " . $t1 . " AND " . $t2 . " ORDER BY request_time DESC LIMIT 3;";  
          
        $r = pg_query($conn, 'BEGIN;');  
        $r = pg_query($conn, 'DECLARE getRecords CURSOR FOR '. $dbQuery);  
          
        for ($i=1; $i < 10; $i++) {  
          echo (10*$i);  
          $r  = pg_query($conn, "FETCH " . (10*$i) . " FROM getRecords;");  
          $row = pg_fetch_all($r);  
          print_r($row);  
        }  
        $r = pg_query('CLOSE getRecords;');  
        $r = pg_query('COMMIT;');  
        
        

        for ($i=0; $i< $nOfRecords; $i++) {
          $r   = pg_query($conn, "FETCH getRecords;");

        Hier steht natürlich noch:
        $row = pg_fetch_array($r);

        Ist mir gar nicht aufgefallen das es fehlt.

        Das LIMIT 3 ist übrigens auch nur zu Testzwecken!

        Kannst Du bei CURSOR auch verwenden.

        Hier noch mal als Beispiel:

        -> Ich arbeite hauptsächlich mit ADOdb (Doku)
        -> bei mir läuft noch PostgreSQL 7

          
        $db->BeginTrans();  
          
        $sql = "DECLARE test CURSOR FOR SELECT id, titel FROM archiv ORDER BY arc_id LIMIT 500";  
        $db->Execute($sql);  
          
        $rs = $db->Execute('FETCH 10 FROM test');  
        $row = $rs->GetArray();  
        print_r($row);  
          
        $rs = $db->Execute('FETCH 20 FROM test');  
        $row = $rs->GetArray();  
        print_r($row);  
          
        $rs = $db->Execute('MOVE 300 IN test');  
          
        $rs = $db->Execute('FETCH 20 FROM test');  
        $row = $rs->GetArray();  
        print_r($row);  
          
        $db->Execute('CLOSE test');  
          
        $db->CommitTrans();  
        
        

        André Laugks

        --
        Die Frau geht, die Hilti bleibt!