Simon: Mysql - Datensatzzeiger-Position auslesen

Ich möchte gerne den Wert der aktuellen Datensatzzeiger-Position herausfinden, den meine aktuelle mysql-query hat. wenn ich die query z.b über WHERE id=17 mache, bekomme ich die dazupassende row geliefert, weiß aber nicht, welchen wert der zeiger besitzt. wie geht das??

Simon

  1. Hello,

    Ich möchte gerne den Wert der aktuellen Datensatzzeiger-Position herausfinden, den meine aktuelle mysql-query hat. wenn ich die query z.b über WHERE id=17 mache, bekomme ich die dazupassende row geliefert, weiß aber nicht, welchen wert der zeiger besitzt. wie geht das??

    Das scheint in PHP nicht implementiert zu sein, oder ich habe es übersehen.
    In der MySQL-API ist es http://dev.mysql.com/doc/refman/5.1/en/mysql-row-tell.html

    Harzliche Grüße vom Berg
    http://bergpost.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

    1. Hello,

      Ich möchte gerne den Wert der aktuellen Datensatzzeiger-Position herausfinden, den meine aktuelle mysql-query hat. wenn ich die query z.b über WHERE id=17 mache, bekomme ich die dazupassende row geliefert, weiß aber nicht, welchen wert der zeiger besitzt. wie geht das??
      Das scheint in PHP nicht implementiert zu sein, oder ich habe es übersehen.
      In der MySQL-API ist es http://dev.mysql.com/doc/refman/5.1/en/mysql-row-tell.html

      verstehe ich den OP falsch, oder passt die vorgeschlagene Lösung nicht zum Problem. Toms Lösung dient dazu, wenn MySQL auf eine Abfrage 27 Datensätze zurückliefert, man mit einer Schleife darüber läuft, dann herauszufinden beim wievielten Satz des Ergebnisse man ist - wenn ich mich da vertue, spart euch die Mühe weiterzulesen *g*

      Der OP möchte wissen, wenn er SELECT FROM WHERE id=17 macht, _einen_ Satz zurückbekommt, der wievielte in der Tabelle das ist - richtig? Wenn dem so ist: die Frage ist bei einer relationalen Datenbank sinnfrei, es gibt von Natur aus keine Reihenfolge, erst durch ein ORDER BY während der Abfrage oder ggf. in Form eines Index erhalten die Sätze eine Reihenfolge. Da dem so ist, gibt es AFAIK keine direkte Methode, die Position eines Datensatzes in einer Tabelle festzustellen, weil diese nicht existiert.

      MfG
      Rouven

      --
      -------------------
      Death is nature's way of telling you to slow down.
      1. Hello Rouven,

        Ich möchte gerne den Wert der aktuellen Datensatzzeiger-Position herausfinden, den meine aktuelle mysql-query hat. wenn ich die query z.b über WHERE id=17 mache, bekomme ich die dazupassende row geliefert, weiß aber nicht, welchen wert der zeiger besitzt. wie geht das??

        Das scheint in PHP nicht implementiert zu sein, oder ich habe es übersehen.
        In der MySQL-API ist es http://dev.mysql.com/doc/refman/5.1/en/mysql-row-tell.html

        verstehe ich den OP falsch, oder passt die vorgeschlagene Lösung nicht zum Problem. Toms Lösung dient dazu, wenn MySQL auf eine Abfrage 27 Datensätze zurückliefert, man mit einer Schleife darüber läuft, dann herauszufinden beim wievielten Satz des Ergebnisse man ist - wenn ich mich da vertue, spart euch die Mühe weiterzulesen *g*

        Der OP möchte wissen, wenn er SELECT FROM WHERE id=17 macht, _einen_ Satz zurückbekommt, der wievielte in der Tabelle das ist - richtig? Wenn dem so ist: die Frage ist bei einer relationalen Datenbank sinnfrei, es gibt von Natur aus keine Reihenfolge, erst durch ein ORDER BY während der Abfrage oder ggf. in Form eines Index erhalten die Sätze eine Reihenfolge. Da dem so ist, gibt es AFAIK keine direkte Methode, die Position eines Datensatzes in einer Tabelle festzustellen, weil diese nicht existiert.

        Ich habe Simon anders verstanden.
        Es ging ihm mMn nicht um die Position in einer Tabelle, sondern um die Position im Stored Resultset und die ist durchaus bestimmbar, da bereits serialisiert und damit eindeutig reproduzierbar, solange das Resultset lebt. Resultsets sind Snapshots, zumindest bei MySQL.

        Aber fragen wir ihn doch einfach danach. Simon, was meintest Du? Die Position des Datensatzes in der Ergebnismenge (Resultset) oder eine Position in der Ausgangsmenge (Tabelle)?

        Harzliche Grüße vom Berg
        http://bergpost.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        1. hi tom,

          Aber fragen wir ihn doch einfach danach. Simon, was meintest Du? Die Position des Datensatzes in der Ergebnismenge (Resultset) oder eine Position in der Ausgangsmenge (Tabelle)?

          ich meine genau ersteres, sollte sich also mit mysql_row_tell() auslesen lassen, oder? nur scheint das über php nicht realisierbar zu sein;-).

          ich kann zwar mit mysql_data_seek () weitersurfen im resultset, aber bekomme aber nicht den tatsächlichen wert der aktuellen reihe des resultsets zu sehen...

          wie geht das also?

          danke!

          Simon

          1. um zu veranschaulichen, was ich machen möchte:

            ich möchte eine datensatznavigation basteln, bei der ich von einer anderen seite komme, die eine beliebig ausgewählte id übergibt. d.h., ich steige auf meiner neuen seite sozusagen irgendwo in der mitte der ergebnisse meiner mysql_query ein. nun möchte ich von hier weg vor und zurücknavigieren. wenn ich von der übergebenen id als startpunkt ausgehe, habe ich das problem, dass ich ja nicht weiß, wie die vorigen/nächsten ids lauten (es können ja z.B. zahlen übersprungen sein).
            deswegen hab ich mir gedacht, es wäre doch elegant, den wert der aktuellen reihe auszulesen und von hier mit plus/minus 1 weiterzu"surfen". ich denke, das wäre doch ein hübscher ansatz für eine einfache navigation, oder nicht? wie gesagt, mysql_row_tell() wäre glaub ich genau das, was ich suche, scheint aber nicht in php zu funktionieren...

            1. Hello,

              [...]

              deswegen hab ich mir gedacht, es wäre doch elegant, den wert der aktuellen reihe auszulesen und von hier mit plus/minus 1 weiterzu"surfen". ich denke, das wäre doch ein hübscher ansatz für eine einfache navigation, oder nicht? wie gesagt, mysql_row_tell() wäre glaub ich genau das, was ich suche, scheint aber nicht in php zu funktionieren...

              Jein.
              Das ist eine sehr alte Aufgabenstellung, die von heutigen Entwicklern, die MySQL einsetzen, immer gerne mit einem "nimm doch limit" weggewischt wird. Das ist aber nicht die Antwort auf die eigentliche Frage, auch wenn es so aussieht, als würde es funktionieren.

              Hier muss man unterscheiden zwischen temporärer (statischer) Ergebnismenge einer Abfrage zum Zeitpunkt X, die "eingefroren" gespeichert wird und und einer dynamischen Ergebnismenge, wenn man nämlich nur die Abfrage (_nicht_ das Ergebnis) speichert.

              Für die buchhalterische Bearbeitung wird auf jeden Fall die Speicherung der Ergebnismenge zum Zeitpunkt X gefordert. Veränderungen werden immer ausgehend von dieser Ergebnismenge durch sogenannte Bewegungsdaten protokolliert.

              Fragt man dann später zum Zeitpunkt X+t neu ab, müssen Ergebnismenge (X) + Bewegungsdaten immer die Ergebnismenge (X+t) ergeben, sonst stimmt etwas mit Deinem Programm nicht und es wird nicht zugelassen.

              Das nur als Ausflug in die Wirklichkeit...

              Zurück zu Deiner eigentlichen Frage:

              Entscheide Dich, worin Du navigieren willst: In einem statischen Ergebnis vom Abfragezeitpunkt (X) (serialisiert) oder in einer dynamsichen Datenmenge (unsortiert).

              Harzliche Grüße vom Berg
              http://bergpost.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
              Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

            2. Moin!

              ich möchte eine datensatznavigation basteln, bei der ich von einer anderen seite komme, die eine beliebig ausgewählte id übergibt. d.h., ich steige auf meiner neuen seite sozusagen irgendwo in der mitte der ergebnisse meiner mysql_query ein. nun möchte ich von hier weg vor und zurücknavigieren. wenn ich von der übergebenen id als startpunkt ausgehe, habe ich das problem, dass ich ja nicht weiß, wie die vorigen/nächsten ids lauten (es können ja z.B. zahlen übersprungen sein).

              Das Problem ist, dass du in deiner Überlegung, ohne es zu bemerken, gleich einen ganzen Haufen von Querys zusammenfaßt, obwohl diese nicht zusammengefaßt werden dürfen.

              Du hast den Query der Übersichtsseite. Wenn du dann eine Detailseite aufrufst, hast du den Query dieser Detailseite. Und wenn du vorwärts oder zurück navigieren willst, hast du nochmal zwei weitere Querys.

              Keiner dieser Querys hängt wirklich mit einem anderen Query zusammen. Allein schon deshalb, weil ja nur kurz das jeweilige Skript aufgerufen wird, die Datenbank abfragt, die Daten in HTML schreibt, zum Browser schickt, und dann alle Daten wieder komplett vergißt. In der Zwischenzeit kann sich in der Datenbank durch andere Benutzer außerdem eine Menge tun.

              Außerdem hat eine Datenbank per Definition erstmal keine Reihenfolge, d.h. die Datensätze sind grundsätzlich wild durcheinander, es gibt kein "vorne/hinten" - außer du definiert eine Sortierreihenfolge. Erst DANN gibt ist die Reihenfolge der abgefragten Datensätze definiert und liegt fest.

              Das gilt allerdings schon nicht mehr für die nächste gleichlautende Abfrage, denn in der Zwischenzeit können ja neue Datensätze dazu gekommen oder entfernt worden sein.

              deswegen hab ich mir gedacht, es wäre doch elegant, den wert der aktuellen reihe auszulesen und von hier mit plus/minus 1 weiterzu"surfen". ich denke, das wäre doch ein hübscher ansatz für eine einfache navigation, oder nicht? wie gesagt, mysql_row_tell() wäre glaub ich genau das, was ich suche, scheint aber nicht in php zu funktionieren...

              row_tell würde dir innerhalb eines einzigen Skriptaufrufes sagen, das wievielte Ergebnis du schon aus der Datenmenge abgerufen hast. Diese Information ist allerdings relativ wertlos, weil du PHP-seitig auch selbst mitzählen könntest, wieviele Datensätze du schon ausgegeben hast. Und üblicherweise will man sowieso ALLE Datensätze, die man abgefragt hat, ausgeben - ansonsten würde man die Abfrage so gestalten, dass man nur genau die Datensätze erhält, die man benötigt, und keine Datensätze ungenutzt wegwerfen. Dieser Ansatz hilft dir also überhaupt nicht.

              Die Grundsatzfrage ist halt: Willst du in den Livedaten der Datenbank navigieren, d.h. zwischenzeitliche Änderungen auch echt sehen. Oder willst du einen Schnappschuß eines zu einer bestimmten Zeit gültigen Zustands durchnavigieren. Die erste Methode ist relativ einfach zu programmieren, die zweite Methode sehr aufwendig.

              Nur als Denkansatz: Wenn du eine eindeutige Sortierung hast, z.B. nach einer ID, und du willst den Datensatz "davor" sehen, dann frage nach der größten ID, die kleiner als die aktuelle ID ist. Für den Datensatz danach frage nach der kleinsten ID, die größer als die aktuelle ID ist.
              Davor: "WHERE id < $aktuelle_id ORDER BY id DESC LIMIT 1"
              Danach: "WHERE id > $aktuelle_id ORDER BY id ASC LIMIT 1"

              Sowas bereitet allerdings Probleme, wenn du mehrere Datensätze hast, die identische Daten im Feld stehen haben, und dieses Feld das einzige Sortierkriterium ist. Du mußt also dafür sorgen, dass z.B. die Sortierung nach Nachname immer eindeutig ist, indem du ein garantiert eindeutiges Feld (UNIQUE- oder PRIMARY-Index autoincrement) mindestens als allerletztes Sortierkriterium hinzufügst.

              - Sven Rautenberg

              --
              "Love your nation - respect the others."
              1. Hello,

                Sowas bereitet allerdings Probleme, wenn du mehrere Datensätze hast, die identische Daten im Feld stehen haben, und dieses Feld das einzige Sortierkriterium ist. Du mußt also dafür sorgen, dass z.B. die Sortierung nach Nachname immer eindeutig ist, indem du ein garantiert eindeutiges Feld (UNIQUE- oder PRIMARY-Index autoincrement) mindestens als allerletztes Sortierkriterium hinzufügst.

                ... oder einen Kombinationsschlüssel baust aus der Duplicate-Spalte und _der_ Unique-Spalte.

                Da kann dann in der Duplicate-Spalte soviel doppelt sein (von mir aus heißen 50% der Leute Meier) wie will, der Treffer ist immer eindeutig zu identifizieren.

                Spannend wird es nur, wenn Du den Meier dann umtaufst in "Zacharias". Was ist dann, wenn Du nun den nächsten (aus der Meier-Liste) suchst? Eine Non-Follow-Strategie ist schon recht aufwändig.

                Harzliche Grüße vom Berg
                http://bergpost.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau
                Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

              2. hi sven,

                Davor: "WHERE id < $aktuelle_id ORDER BY id DESC LIMIT 1"
                Danach: "WHERE id > $aktuelle_id ORDER BY id ASC LIMIT 1"

                ...das wäre also die naviagation in der db,

                ich hab inzwischen eine variante gebastelt, die innerhalb der erstellten query hin- und herwandert. das script sieht so aus und scheint zu fiunktionieren:

                $sql = "SELECT *FROM kontakte ";

                $result = mysql_query ($sql, $conn);

                $menge = mysql_num_rows ( $result );

                if ($result)
                        {

                mysql_data_seek ($result, $_GET['zahl']);
                  $row = mysql_fetch_row($result);
                  echo $row[0] . "<br>";
                  echo $row[1] . "<br>";
                  echo $row[2];

                $plus= $_GET['zahl']+1;
                  $minus= $_GET['zahl']-1;
                  echo $menge;

                $zahl=$_GET['zahl'];

                if($zahl > 0 ){

                echo "<a href=".$_SERVER['PHP_SELF']."?zahl=$minus>zur&uuml;</a>";}

                }
                  if($zahl < ($menge - 1)){
                  echo "<a href=".$_SERVER['PHP_SELF']."?zahl=$plus>weiter</a>";
                  }

                }

                bitte sagt mir, ob das so "erlaubt" ist. da ich ja nichts in die db schreibe, müßte das doch gehen, oder?

                1. Moin!

                  hi sven,

                  Davor: "WHERE id < $aktuelle_id ORDER BY id DESC LIMIT 1"
                  Danach: "WHERE id > $aktuelle_id ORDER BY id ASC LIMIT 1"

                  ...das wäre also die naviagation in der db,

                  Insbesondere fragt es nur genau einen Datensatz ab, nicht mehr.

                  ich hab inzwischen eine variante gebastelt, die innerhalb der erstellten query hin- und herwandert. das script sieht so aus und scheint zu fiunktionieren:

                  $sql = "SELECT *FROM kontakte ";

                  Das fragt ALLE Datensätze ab, und schmeißt dann später alle bis auf einen weg.

                  Effizienz sieht anders aus.

                  bitte sagt mir, ob das so "erlaubt" ist. da ich ja nichts in die db schreibe, müßte das doch gehen, oder?

                  Ja, es "funktioniert". Aber stell dir vor, du hättest hunderttausend Datensätze. Erstens will man die wohl niemals alle nacheinander durchnavigieren, und zweitens will man die garantiert nicht immer komplett aus der Datenbank abfragen, um sie dann nicht zu benutzen.

                  - Sven Rautenberg

                  --
                  "Love your nation - respect the others."
                  1. Ja, es "funktioniert". Aber stell dir vor, du hättest hunderttausend Datensätze. Erstens will man die wohl niemals alle nacheinander durchnavigieren, und zweitens will man die garantiert nicht immer komplett aus der Datenbank abfragen, um sie dann nicht zu benutzen.

                    hast schon recht, mir gings nur ums prinzip, weil ich mir das halt grade durchüberlegt hab. in meinem fall wär das mit den datensätzen auch tatsächlich kaum relevant, weil es nur max. hundert datensätze á 8 felder sind.

                    aber du hast natürlich mit der anderen variante den vogel abgeschossen...
                    danke nochmal!

                    simon

                2. Hello Simon,

                  $sql = "SELECT *FROM kontakte ";

                  $result = mysql_query ($sql, $conn);

                  $menge = mysql_num_rows ( $result );

                  if ($result)
                          {

                  Das ist verkehrt herum.

                  $sql = "SELECT *FROM kontakte ";
                    $result = mysql_query ($sql, $conn);

                  if (mysql_errno($conn) == 0)
                    {
                      if ($result)
                      {
                        $menge = mysql_num_rows ( $result );

                  # ...

                  }
                      else
                      {
                        ## kein Datensatz da, der den Abfragekriterien entspricht
                      }
                    }
                    else
                    {
                      ## Fehler bei der Abfrage. log -> mysql_error($conn);
                    }

                  Es gibt ja auch noch eine Alternative:

                  Man kann das Resultset auch abholen und dann das Array mit den Datensätzen in der Session zwischenspeichern. Dann muss nicht jedes Mal ein neues Query durchgeführt werden und man hat eine eingefrorene Momentdarstellung (Snapshot) zum Zeitpunkt der Abfrage.

                  Harzliche Grüße vom Berg
                  http://bergpost.annerschbarrich.de

                  Tom

                  --
                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                  Nur selber lernen macht schlau
                  Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

          2. Hello,

            Aber fragen wir ihn doch einfach danach. Simon, was meintest Du? Die Position des Datensatzes in der Ergebnismenge (Resultset) oder eine Position in der Ausgangsmenge (Tabelle)?

            ich meine genau ersteres, sollte sich also mit mysql_row_tell() auslesen lassen, oder? nur scheint das über php nicht realisierbar zu sein;-).

            ich kann zwar mit mysql_data_seek () weitersurfen im resultset, aber bekomme aber nicht den tatsächlichen wert der aktuellen reihe des resultsets zu sehen...

            wie geht das also?

            Du hast zwei Möglichkeiten bei MySQL, Resultsets zu verarbeiten. Du kannst sie "Raw" auf die Schnittstelle klatschen, dann verhalten sie siche wie eine gute alte Textdatei, die nur vorwärts lesbar ist. Das erreichst Du über PHP, indem Du ein unbuffered Query anforderst.

            http://de3.php.net/manual/de/function.mysql-unbuffered-query.php

            Das resultset eines unbuffered Query musst Du auf jeden fall vollständig abholen und danach auch wieder freigeben mit [PHP]mysql_free_result()

            Die zweite Möglichkeit ist das "normale" [PHP]mysql_query().
            Hier werden Dir die Daten von MySQL in einem Ausgangsspeicherbereich aufbereitet angeboten. Du hast Zusatzinformationen, wie [PHP]mysql_num_rows() usw. zur Verfügung, kannst in dem Resultset navigieren, jede Zeile und sogar jedes Feld einzeln ansprechen. Und Du musst es nicht vollständig abholen. Wenn Du es nicht mehr brauchst, musst Du es trotzdem mit [PHP]mysql_free_result() wieder freigeben.

            Navigieren über die Datensätze kannst Du mittels [PHP]mysql_data_seek()
            http://de3.php.net/manual/de/function.mysql-data-seek.php

            Das stellt den Zeiger im resultset auf die gewünschte Zeile der Ausgabemenge.
            Mittels [PHP]mysql_fetch_row() oder ~_assoc() usw. kannst Du nun die Zeile "abholen" und in eine PHP-Array übertragen. http://de3.php.net/manual/de/function.mysql-fetch-assoc.php
            Danach steht der zeige im Resultset hinter dieser Zeile, also auf dem Anfang der nächsten.

            Du benötigst also gar nicht unbedingt eine Funktion, die Dir angibt, wo der Zeiger steht, denn Deine Applikation weiß ja, wo sie ihn hingestellt hat. Da sich das Resultset nicht ändern kann, solange es lebt, ist das immer reproduzierbar. Du kannst den Zeiger also vor dem Lesezugriff (andere sind ja nicht erlaubt) immer so positionieren, wie Du magst.

            Erlaubte Werte liegen im Bereich von 0 bis (Satzanzahl - 1). Aber das steht ja auch im PHP-Manual.

            Harzliche Grüße vom Berg
            http://bergpost.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
            Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)