Multi Query vernünftiges Error Handling
TypischeFrage
- php
Hi!
Ich habe mal gerade zum Testen dieses kleine Script zusammen gebastelt:
<?php
$test = new mysqli("localhost","root","","journaldatabase");
// Some starting variables
$Query = array();
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 3";
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 'lkasjdg'";
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 5";
$Query = implode(";",$Query);
$Errors = array();
// Execute multi query
if ($test->multi_query($Query)) {
do {
// Current result set
$Result = $test->store_result();
$Errors[] = $test->error;
var_dump($Result);
echo $Result->num_rows. " result found<br />";
$Result->close();
}
while ($test->next_result() && $test->more_results());
}
var_dump($Errors);
?>
Was ich erreichen möchte ist, dass ich am Ende ein Array an Fehlermeldungen habe, wie z.B: "Query 3 ist fehlgeschlagen, Query 5 ist fehlgeschlagen", etc. Aber wie catch man Fehler in Multi Querys vernünftig? Ich hab jetzt schon einige Zeit danach gegoogelt und scheinbar haben andere ebenfalls dieses Problem. Nur nirgendswo finde ich eine verünftige Antwort.
Was ich mittlerweile gelernt habe ist, dass beim ersten Fehler das ganze abbricht und weitere Querys NICHT ausgeführt werden. (Das möchte ich allerdings auch nicht!). Jedenfalls funktioniert mein Beispiel da oben bisher so, dass er jedes einzelne Resultset durchgeht und eigentlich mit $Errors[] = $test->error; die gerade aufgetretene Fehlermeldung an $Errors weiterleiten sollte. Tut er aber irgendwie nicht bei der zweiten Query, die ich ja absichtlich fehlerhaft gestaltet habe. Also wie stelle ich das jetzt vernünftig an? Die Beispiele auf php.net sind nicht wirklich zielführend.
Ich bin auch schon auf die Idee gekommen einfach if(count($Query) === count($Errors)) zu machen, allerdings weiß ich dann nur, ob die vorgesehene Anzahl an Querys - also alle vorhandenen - ausgeführt wurde und keine mit Fehlern abgebrochen ist, ich möchte aber bitte wissen WELCHE mit Fehler abgebrochen ist und was die Fehlermeldung war. Nur irgendwie funktioniert das mit meinem $test->error; nicht ganz.
Weiß da jemand Rat?
Vielen dank.
Hi,
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 3";
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 'lkasjdg'";
Tut er aber irgendwie nicht bei der zweiten Query, die ich ja absichtlich fehlerhaft gestaltet habe.
Wenn die erste Query keinen Fehler gibt, warum sollte es dann die zweite?
Eine nummerische Spalte mit einem String zu vergleichen, ist kein Fehler. Es liefert nur möglicherweise ein leeres Ergebnis.
MfG ChrisB
Wenn die erste Query keinen Fehler gibt, warum sollte es dann die zweite?
Eine nummerische Spalte mit einem String zu vergleichen, ist kein Fehler. Es liefert nur möglicherweise ein leeres Ergebnis.
Hm stimmt. Ich hatte einfach vor eine fehlerhafte Query zu liefern und habe einfach schnell = 'aklsjdgh' eingetippt, ohne nachzudenken (da derartige Werte nicht in der itemID Spalte auftreten). Daher meine irrige Annahme.
Es bleibt aber dabei: Selbst wenn ich das bedenke worauf du mich gerade hingeweisen hast und eine dann auch wirklich fehlerhafte Query einbaue - Das Ding bricht einfach ab und führt alle weiteren Querys nicht mehr aus, was nicht sein darf (Wie umgehe ich das?) und ich erhalte, wenn ich dann $Errors() ausgebe mit der mitgeschriebenen Fehlermeldung keinerlei Hinweis darauf welche Query genau fehlgeschlagen ist.
Also:
1. Wie lasse ich die multi_query weiterlaufen, auch wenn eine Unterquery fehlschlägt?
2. Habe ich innerhalb der Result Verarbeitung einer multi_query Zugriff auf die ausgeführten Querys und weiß bei welcher ich gerade bin?
hi,
gute Erfahrungen habe ich mit der Fehlerbehandlung über Exceptions und Exception Chaining, wobei PDO sehr gute Voraussetzungen dazu bietet.
Hotti
Tach!
if ($test->multi_query($Query)) {
Du hast zwar das Beispiel aus dem PHP-Handbuch kopiert, aber du hast den Satz darüber anscheinend nicht gelesen.
"Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli_next_result() first."
Und das Beispiel orientiert sich auch nicht daran, sondern fragt die Ergebnisse nur ab, wenn multi_query() kein false liefert und damit nur, wenn das erste Statement keinen Fehler bringt.
Ich hab jetzt schon einige Zeit danach gegoogelt und scheinbar haben andere ebenfalls dieses Problem. Nur nirgendswo finde ich eine verünftige Antwort.
Ich kenne sie auch nicht, aber wenn du das herausfinden möchtest, musst du kreativer sein. Lass die Abbruchbedingungen weg, nimm nur eine next_result-Schleife. Schreib den Code mal so, wie ihn ein Anfänger schreiben würde, also so, als ob nie Fehler auftreten könnten (aber vermeide Endlosschleifen). Und nun spick den Code mit var_dump()s. Schau dir an, wann welche Funktion welchen Rückgabewert produziert.
dedlfix.
Tach!
Und nun spick den Code mit var_dump()s. Schau dir an, wann welche Funktion welchen Rückgabewert produziert.
Dazu natürlich auch die üblichen Verdächtigen, wie mysqli::$error und Konsorten - alles was laut Beschreibung im Handbuch irgendeine Art von Fehler-Information liefern kann.
dedlfix.
Du hast zwar das Beispiel aus dem PHP-Handbuch kopiert, aber du hast den Satz darüber anscheinend nicht gelesen.
Doch.
"Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli_next_result() first."
Und next_result() rufe ich ja auf, in der while schleife...
Und das Beispiel orientiert sich auch nicht daran, sondern fragt die Ergebnisse nur ab, wenn multi_query() kein false liefert und damit nur, wenn das erste Statement keinen Fehler bringt.
Das hatte ich vergessen, habe einfach eine Query als erstes eingefügt, die immer zutrifft. Somit wird multi_query() immer ausgeführt und alle folgenden Querys sollten abgearbeitet werden.
Übrigens muss es eine while() Schleife sein, da ich nicht weiß wieviele Querys es letztendlich werden. Und was auch noch wichtig ist: Die einzige Schleife die ich habe ist die do while Schleife mit next_result(). Was meinst du also bitte mit vermeide Endlosschleifen? Es gibt hier keine! Und das
do { }
while ($test->next_result() && $test->more_results());
Ist notwendig, da sonst ein StrictStandards Error kommt.
Tach!
Du hast zwar das Beispiel aus dem PHP-Handbuch kopiert, aber du hast den Satz darüber anscheinend nicht gelesen.
Doch.
Aber nicht verstanden, oder warum baust du dann deinen Code so, dass er bei einem Fehler im ersten Statement aufhört, obwohl du das nicht willst?
Übrigens muss es eine while() Schleife sein, da ich nicht weiß wieviele Querys es letztendlich werden.
Es geht (mir) doch jetzt erst einmal darum, zu testen wie sich das System verhält. Dass am Ende irgendwas herauskommt, dass deine realen Bedingungen erfüllt, ist jetzt erst einmal nebensächlich.
Und was auch noch wichtig ist: Die einzige Schleife die ich habe ist die do while Schleife mit next_result(). Was meinst du also bitte mit vermeide Endlosschleifen? Es gibt hier keine!
Nein, noch nicht, aber wenn du meiner Empfehlung folgst, ein Testszenario ohne Abbruchbedingungen aufzubauen (weil vielleicht next_result() nicht nur am Ende sondern auch im Fehlerfall false liefern könnte), kann es sich schnell so ergeben. Abbruchbedingungen schließen die while-Schleife mit ein. while(true) ist aber auch nicht geeignet, weil derzeit nicht klar ist, wie die konkrete Abbruchbedingung inklusive aller Fehler aussieht. Du solltest also hier bei drei Test-Abfragen nur 3 oder höchstens 4 Schleifendurchläufe fest kodiert erstellen. Und dabei zuschauen, welche Funktion und Eigenschaft was zurückgibt beziehungsweise enthält.
dedlfix.