Mysqli und prepare

Servus bplaced’ler,

ich habe folgendes Konstrukt mehrmals, weil ich desöfteren rekursiv über Joins nach etwas suche:

$param1 = "irgendwas"; $query = "Ein query"; $stmt = $mysqli->prepare($query); $stmt->bind_param("s", $param1); while(true) { // da passiert viel; unter anderem ein fetch(); um param1 zu überschreiben // break, wenn etwas gefunden wurde }

Ich muss sowohl den query, bind_param() als auch das Prepare in die while-Schleife einfügen (auch nur $query draußen zu lassen führt zum selben Fehler). Warum ist meine Frage? Prepare ist doch dazu da, um die Datenbank auf eine Abfrage vorzubereiten. Die Parameter sind doch egal und müssen mindestens vor dem Execute definiert werden.

Die Fehlermeldung “stmt counldn’t be executed in line …” ist auch nicht aufschlussreich, da weder errno noch error gesetzt werden.

Folgendermaßen funktioniert die Abfrage

[code]while(true) {
$param1 = “irgendwas”;
$query = “Ein query”;
$stmt = $mysqli->prepare($query);
$stmt->bind_param(“s”, $param1);
// da passiert viel; unter anderem ein fetch(); um param1 zu überschreiben
// break, wenn etwas gefunden wurde
}

// folgendes funktioniert auch nicht
$query = “Ein query”;
while(true) {
$param1 = “irgendwas”;
$stmt = $mysqli->prepare($query);
$stmt->bind_param(“s”, $param1);
// da passiert viel; unter anderem ein fetch(); um param1 zu überschreiben
// break, wenn etwas gefunden wurde
}[/code]

Schwer nachzuvollziehen, insb. wenn du nicht mal zeigst was genau du machst, sondern das nur mit „da passiert nicht viel“ abtust.

Dass du das Ergebnis einer Query erst vollständig gefetched haben musst, bevor du eine neue Query ausführen kannst¹, hast du aber schon berücksichtigt …?

¹ Außer wenn du erst mal das komplette Result vom MySQL-Server auf Client zwischenlagerst, mittels store_result.

Ok, einfaches Beispiel

$id = "home"; $lng = "initial_lng"; $content = ""; $query1 = "SELECT `content` FROM `table2` WHERE `id` = ? AND `lng` = ?;"; $query2 = "SELECT `parent_lng` FROM `table1` WHERE `lng` = ?;"; $stmt1 = $mysqli->prepare($query1); $stmt2 = $mysqli->prepare($query2); $param1 = 0; $param2 = ""; $param3 = ""; $stmt1->bind_param("is", $param1, $param2); $stmt2->bind_param("s", $param3); while(true) { $param1 = $id; $param2 = $lng; $stmt1->execute(); if ($stmt1->affected_rows > 0) { $stmt1->bind_result($content); $stmt1->fetch(); break; } else if ($stmt1->affected_rows == -1) { // eigentlich sollte man vorher $stmt1->execute(); auf false überprüfen throw new Exception($stmt1->errno.": ".$stmt1->error); } else { $param3 = $lng; $stmt2->execute(); $stmt2->bind_result($lng); $stmt2->fetch(); if ($lng == null || $lng == "") { $content = "error"; break; } } } $stmt1->close(); $stmt2->close();

Kann mir aber jemand sagen, wie ich mysqli_stmt::execute() debuggen kann (es geht nicht um oben). Denn mysqli_stmt::$affected_rows liefert mir -1, aber weder die errno von mysqli noch die von mysqli_stmt ist gesetzt bzw. sind beide auf 0 und error “”; auch $stmt->execute() liefert mir den boolschen Wert true.

Wieso nutzt du überhaupt affected_rows – für Queries, die gar keine Daten verändern, sondern nur welche auslesen?

Für SELECT-Statements solltest du num_rows benutzen.

:hail: ja, danke, habe ich gerade in der doku gelesen :hail: (ich war mit edit zu langsam)

und ich wundere mich seit über 2 Stunden, warum execute true zurückgibt. Wer lesen kann, ist im Vorteil. Alle meine bisherigen Abfragen waren Insert usw., denn ich ändere gerade einen bestehenden Code von mehrern Tausend Zeilen ab.

store_result() klingt vernünftig. Danke

[edit]Dieses store_result() verstehe ich nicht ganz. Gemäß der Doku werden über den Treiber die Daten in das Skript geladen. Das ist ja schön und gut. Wie passiert das bei mysqli_stmt::fetch()? Wird dort nur die eine Zeile geholt? Denn wenn ich mysqli_stmt::store_result() mache, holt er alles rüber und braucht es nicht bei jedem mysqli_stmt::fetch() machen. Bei großen Datenmengen kann das memory_limit überschritten werden, das weiß ich. So jetzt die eigentliche Frage: Wenn ich ohne prepared statements arbeite, werden dort bei einem SELECT die Daten mit dem Absetzten des Querys komplett geholt? Ich hoffe nicht! Aber dann stellt sich die Frage, warum es dann nicht zum Fehler kommt, wenn ich innerhalb der while()-Schleife eine weitere Abfrage sende, denn eigentlich ist ja noch eine Abfrage aktiv?
Sorry, bei dem mysqli-Treiber passiert ganz schön viel Magie und die Doku sagt auch nicht viel dazu.

Jetzt treten natürlich die php-Hasser auf den Plan. Seid einfach ruhig! php ist inkonsistent, aber das ist mir egal. Wenn man sie kennt, kann man auch Dinge, die zum Fehler führen übergehen. Ein paar Dinge wurden ja jetzt schon weggelassen.[/edit]