Verstaendnisfrage query vs. fetch

Verstaendnisfrage query vs. fetch

am 27.11.2006 17:06:53 von Lars Uhlmann

folgendes Stück code sei gegeben:

,-----
| 1: $this->mysqli = @new mysqli(...);
| 2: $result = $this->mysqli->query("SELECT ...");
| 3:
| 4: if( $result )
| 5: {
| 6: while( $row = $result->fetch_array(MYSQLI_NUM) )
| 7: {
| 8: $this->last_result[] = $row;
| 9: }
|10: }
|11: $result->close();
|12: $this->mysqli->close();
`-----

In Zeile 1 wird die query an MySQL geschickt und MySQL liefert ein
Ergebnis an PHP zurück. Zeile 6 formatiert das Ergebnis dann
entsprechend um. Wenn die query also erfolgreich war und Datensätze
geliefert hat, ist dann 'fetch_array()' unabhängig von der noch
bestehenden Verbindung zur Datenbank in der Lage, alle Datensätze zu
parsen? Oder anders gefragt, könnte man theoretisch 'mysqli->close()'
nach Zeile 3 verlagern, ohne das 'fetch_array()' davon betroffen ist?

Hintergrund ist die Fehlerbehandlung. Wenn $result ungleich FALSE ist
und SELECT auch Datensätze zurückliefert, kann 'fetch_array()' diese
auch auslesen, wenn just zu diesem Zeitpunkt die Datenbankverbindung
abbricht?

Oder anders gefragt: Stimmt die Annahme das 'query()' die eigentliche
Kommunikation mit dem Datenbankserver abwickelt, das Ergebnis im
mysqli-Objekt speichert und 'fetch_{array|row|...}()' nur noch
wie angefordert umformatiert, ohne nochmals mit dem Dbs in Verbindung
zu treten?

Danke
Lars

Re: Verstaendnisfrage query vs. fetch

am 27.11.2006 17:46:44 von sk

Lars Uhlmann schrieb:

> | 2: $result = $this->mysqli->query("SELECT ...");
> | 3: | 4: if( $result )
> | 5: {
> | 6: while( $row = $result->fetch_array(MYSQLI_NUM) )

> In Zeile 1 wird die query an MySQL geschickt und MySQL liefert ein
> Ergebnis an PHP zurück. Zeile 6 formatiert das Ergebnis dann
> entsprechend um. Wenn die query also erfolgreich war und Datensätze
> geliefert hat, ist dann 'fetch_array()' unabhängig von der noch
> bestehenden Verbindung zur Datenbank in der Lage, alle Datensätze zu
> parsen? Oder anders gefragt, könnte man theoretisch 'mysqli->close()'
> nach Zeile 3 verlagern, ohne das 'fetch_array()' davon betroffen ist?

Nein. query() startet die Abfrage. Wenn etwas schief geht (=false) mit
errno() oder error() prüfen was daneben geht. Daten werden erst im
fetch_array() gesendet.

> Hintergrund ist die Fehlerbehandlung. Wenn $result ungleich FALSE ist
> und SELECT auch Datensätze zurückliefert, kann 'fetch_array()' diese
> auch auslesen, wenn just zu diesem Zeitpunkt die Datenbankverbindung
> abbricht?

Nein. bei Abbruch sind evtl. die Daten noch nicht angekommen. Also hier
eine Fehlerbehandlung einbauen.

> Oder anders gefragt: Stimmt die Annahme das 'query()' die eigentliche
> Kommunikation mit dem Datenbankserver abwickelt, das Ergebnis im
> mysqli-Objekt speichert und 'fetch_{array|row|...}()' nur noch
> wie angefordert umformatiert, ohne nochmals mit dem Dbs in Verbindung
> zu treten?

Das stimmt so nicht. Es es ist möglich das Daten schon im ersten Paket
gesendet werden, muss aber nicht sein. Fetch_xxx() lädt immer Daten
nach. Bei Blobs sogar in Chunks (nur mysqli) damit es keinen Ärger mit
der Packetgrösse gibt.

Eine anständige Fehlerbehandlung nach Zeile 2+6 ist dein Freund und
Sorgenvermeider.

Jörg

Re: Verstaendnisfrage query vs. fetch

am 27.11.2006 17:56:51 von Lars Uhlmann

Jörg Singendonk schrieb:

>> | 2: $result = $this->mysqli->query("SELECT ...");
>> | 3:
>> | 4: if( $result )
>> | 5: {
>> | 6: while( $row = $result->fetch_array(MYSQLI_NUM) )
>
> [...]
>
> Eine anständige Fehlerbehandlung nach Zeile 2+6 ist dein Freund und
> Sorgenvermeider.

Nach Zeile 6 muß also 'mysqli->errno' gleich 0 sein, wenn ich
sicherstellen will, daß die Abfrage korrekt abgearbeitet wurde?

Lars

Re: Verstaendnisfrage query vs. fetch

am 27.11.2006 18:12:14 von sk

Lars Uhlmann schrieb:

> 6: while( $row = $result->fetch_array(MYSQLI_NUM) )
> 7: {
> 8: $this->last_result[] = $row;
> 9: }

> Nach Zeile 6 muß also 'mysqli->errno' gleich 0 sein, wenn ich
> sicherstellen will, daß die Abfrage korrekt abgearbeitet wurde?

So oder besser hinter 9 auf > 0 testen. Dann hast du die Fehlerabfrage
nicht in der Schleife und weißt aus was passiert ist.

Btw: "$this->last_result[] = $row;" kann dir bei vielen Zeilen eine Out
of Memory kondition einbringen. Dann stirbt das ganz Script und es
bekommt nix davon mit.

Jörg

Re: Verstaendnisfrage query vs. fetch

am 27.11.2006 18:33:26 von Lars Uhlmann

Jörg Singendonk schrieb:

>> 6: while( $row = $result->fetch_array(MYSQLI_NUM) )
>> 7: {
>> 8: $this->last_result[] = $row;
>> 9: }
>
>> Nach Zeile 6 muß also 'mysqli->errno' gleich 0 sein, wenn ich
>> sicherstellen will, daß die Abfrage korrekt abgearbeitet wurde?
>
> So oder besser hinter 9 auf > 0 testen. Dann hast du die
> Fehlerabfrage nicht in der Schleife und weißt aus was passiert ist.

Ja, meinte ich eigentlich auch so. Die Schleife bricht ja ab, falls
'$row' FALSE ist.

> Btw: "$this->last_result[] = $row;" kann dir bei vielen Zeilen eine
> Out of Memory kondition einbringen. Dann stirbt das ganz Script und
> es bekommt nix davon mit.

Stimmt, da gibt es ja diese möglichen Beschränkungen in PHP bezüglich
Laufzeit und Speicher.
Wie macht man's besser? Einfach nur eine bestimmte Anzahl Zeilen lesen
vermeidet diesen Fall ja auch nicht.

Danke
Lars

Re: Verstaendnisfrage query vs. fetch

am 27.11.2006 19:02:47 von sk

Lars Uhlmann schrieb:

> Stimmt, da gibt es ja diese möglichen Beschränkungen in PHP bezüglich
> Laufzeit und Speicher.
> Wie macht man's besser? Einfach nur eine bestimmte Anzahl Zeilen lesen
> vermeidet diesen Fall ja auch nicht.

Wenn du weißt das nur nur ein paar Zeilen sind (z.b. 170x Ländernamen)
oder 20 Fälle für ein Option-tag ist das möglicherweise unsauber aber ok.

Wenn du damit rechnen muss das du z.b. 8000 Adressen a ca.1kByte Daten
liest, musst du die Zeilen einzeln verarbeiten - also innerhalb der
Schleife.

Musst du selber abschätzen. Wenn "memory_limit" zuschlägt ist dein
Script erledigt.

Jörg