2013-01-10 3 views
5

Ho già chiesto qualcosa sull'errore di cattura in una query multipla in PHP qualche tempo fa, ma nessuno ha risposto. Ora ho cercato su Google un po 'di più e ho capito un po' di più del problema.Lasciando una query multipla PHP continua se si verificano errori

ho ottenuto questo codice:

// Some starting variables 
$test = new mysqli("localhost","root","","testdatabase"); 
$Query = array(); 
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 3"; 
$Query[] = "SELECT 'wos' FROM items WHERE itemID"; 
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 5"; 
$Query = implode(";",$Query); 
$Errors = array(); 

// Execute multi query 

if ($test->multi_query($Query)) { 
    do { 
    // fetch results 
    $Result = $test->store_result(); 
    print_r($Result); 
    if($test->errno === 0) { 
      echo $Result->num_rows . "<br>"; 
    } 
    else { 
     $Errors[] = $test->error; 
    } 
    $Result->close(); 

    if (!$test->more_results()) { 
     break; 
    } 
    if (!$test->next_result()) { 
     $Errors[] = $test->error; 
     break; 
    } 
    } while (true); 
} 

Come potete vedere ho un certo numero di query successive X e voglio compiere tutti. Pertanto, se la query 2 non riesce, desidero continuare la multi-query per consentire l'esecuzione delle seguenti query. Come posso fare questo?

Inoltre, se si verifica un errore, desidero salvare questo errore in $Errors. Tuttavia attualmente non funziona come previsto poiché posso solo salvare il messaggio di errore ma non la query corrispondente. Solo il messaggio di errore non è molto utile senza la query che non ha funzionato. Quindi voglio avere qualcosa come: "Query 3 failed ('SELECT ...'): 'ERROR MESSAGE'".

Com'è possibile? Sono in grado di ottenere l'errore corrente nel ciclo con $test->error, ma non ho nulla come $test->currentsubsequentquery. Come lo posso fare?

Grazie mille.

+0

Non vedo da nessuna parte dove $ test è definito o nessuno dei metodi che sta chiamando. Impossibile aiutare se non sappiamo cosa sta facendo il tuo codice. – Kyle

+0

$ test = new mysqli ("localhost", "root", "", "testdatabase"); – Shiuyin

+0

Se gli errori SQL sono un possibile risultato previsto, allora stai facendo qualcosa di sbagliato. Stai facendo qualcosa di simile a un client SQL (o terminale) perché hai davvero bisogno di eseguire tante query contemporaneamente? –

risposta

0

Il problema qui è qualcosa che potrebbe essere definito un limite nel protocollo MySQL. Quando si utilizza la query multipla (dalla prospettiva MySQL: impostando l'opzione multi statement su On e quindi inviando una query) il server lo dividerà e li eseguirà uno dopo l'altro. Le risposte saranno inviate senza riferimento all'origine. L'unico modo in cui un client (in questo caso PHP/mysqli) potrebbe capire a quale istruzione reale si riferisce un errore, dovrebbe analizzare la stringa di query completa e provare a fare un po 'di mappatura. Ma questo non funzionerà in molti casi: alcune dichiarazioni, in particolare CALL, possono restituire più set di risultati che non possono essere mappati su un'istruzione.

Se vuoi sapere di più su l'errore ci sono due scelte:

Il brutto sta facendo $Query = implode(";\n\n",$Query); e quindi analizzare il messaggio di errore per la linea fornito e corrispondono a quelli.

O semplicemente non utilizzare multi_query. multi_query è pensato per gestire chiamate di stored procedure che restituiscono più set di risultati. L'uso di multi_query in un caso come sopra, consente di risparmiare solo una piccola latenza, poiché il server può elaborare direttamente la query successiva senza attendere il successivo comando di query, ma anche quello può essere raggiunto utilizzando le operazioni di query asincrona di mysqlnd.

0

Bene, più query in una singola istruzione non sono generalmente una buona idea. I buoni client SQL (ad esempio PDO) non consentono più query poiché in questo modo l'iniezione SQL è resa molto più difficile. vorrei dissuadere dalla vostra idea e proporre una delle seguenti soluzioni:

  • Usa tre affermazioni singoli
  • Dal momento che i tre quesiti sono molto simili, è necessario utilizzare una dichiarazione preparata ed eseguirlo tre tempi con diversi parametri vincolanti. Ciò fornisce prestazioni migliori rispetto a tre singole affermazioni e rende impossibile l'iniezione SQL.
  • si potrebbe progettare una query uno-per-tutti come questo o fare qualsiasi cosa con UNION:

    "SELECT 'wos' FROM items WHERE itemID IN ('3', '5')" 
    

Se ora si pensa "che cosa è questo tizio parlando?Questo non sarà più atomico. "Allora dovresti usare una transazione ...

+0

"Questo non sarà più atomico." - multi_query non è atomico – johannes

+0

@johannes: sì, ma si potrebbe pensare che –

+0

Ecco perché ho chiarito :-) – johannes