2013-01-10 15 views
5

Już wcześniej zapytałem coś o łapanie błędów w wielu zapytaniach w PHP, ale nikt nie odpowiedział. Teraz trochę googlowałem i zrozumiałem nieco więcej problemu.Pozwalanie na wykonywanie wielu zapytań PHP, jeśli wystąpią błędy

mam ten kod:

// 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); 
} 

Jak widać mam szereg X kolejnych zapytań i chcesz je wszystkie wykonać. Więc jeśli zapytanie 2 zakończy się niepowodzeniem, chcę kontynuować wielo-kwerendę, aby umożliwić uruchomienie następujących zapytań. Jak mogę to zrobić?

Ponadto, jeśli wystąpi błąd, chcę zapisać ten błąd w numerze $Errors. Jednak obecnie nie działa tak jak należy, ponieważ mogę zapisać tylko komunikat o błędzie, ale nie odpowiednie zapytanie. Tylko komunikat o błędzie nie jest naprawdę pomocny bez zapytania, które nie powiodło się. Więc chcę mieć coś takiego: "Query 3 failed ('SELECT ...'): 'ERROR MESSAGE'".

Jak to jest możliwe? Jestem w stanie uzyskać bieżący błąd w pętli z $test->error, ale nie mam nic takiego jak $test->currentsubsequentquery. Jak mogę to zrobić?

Wielkie dzięki.

+0

Nie widzę nigdzie miejsca, w którym zdefiniowano $ test lub jakiejkolwiek metody, do której się dzwoni. Niemożliwe, aby pomóc, jeśli nie wiemy co robi twój kod – Kyle

+0

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

+0

Jeśli błędy SQL są możliwym, oczekiwanym rezultatem, to robisz coś nie tak. "Robimy coś w rodzaju klienta SQL (lub terminala), dlaczego tak naprawdę potrzebujesz wykonać tyle zapytań naraz?" –

Odpowiedz

0

Kwestia tutaj jest czymś, co można nazwać ograniczeniem w protokole MySQL. Podczas korzystania z wielu zapytań (z perspektywy MySQL: ustawienie opcji wielu instrukcji na On, a następnie wysłanie zapytania) serwer podzieli to i wykona je jeden po drugim. Odpowiedzi będą wysyłane bez odniesienia do miejsca pochodzenia. Jedyny sposób, w jaki klient (w tym przypadku PHP/mysqli) mógłby zorientować się, do której rzeczywistej instrukcji odnosi się błąd, musiałby sparsować cały łańcuch zapytania i spróbować wykonać pewne mapowanie. Ale to nie zadziała w wielu przypadkach - niektóre stwierdzenia, w szczególności CALL, mogą zwracać wiele zestawów wyników, których nie można przypisać do instrukcji.

Jeśli chcesz wiedzieć więcej na temat tego błędu istnieją dwie możliwości:

Brzydki jeden robi $Query = implode(";\n\n",$Query); a następnie analizować komunikat o błędzie dla przewidzianej linii i zgadzać się.

Lub po prostu nie używaj multi_query. multi_query służy do obsługi wywołań procedur przechowywanych, zwracających wiele zestawów wyników. Użycie multi_query w przypadku takim jak powyższe zaoszczędzi ci tylko niewielkiego opóźnienia, ponieważ serwer może bezpośrednio przetworzyć następne zapytanie bez czekania na kolejne polecenie zapytania, ale nawet to można osiągnąć za pomocą operacji asynchronicznych zapytań mysqlnd.

0

Cóż, wiele zapytań w jednym wyciągu nie jest dobrym pomysłem. Dobre klienty SQL (na przykład PDO) nie dopuszczają w ogóle wielu zapytań, ponieważ w ten sposób SQL injection jest znacznie trudniejsze. Chciałbym cię odwieść od swojego pomysłu i zaproponować jedno z następujących rozwiązań:

  • Zastosowanie trzy pojedyncze wypowiedzi
  • Ponieważ twoje trzy pytania są bardzo podobne, należy użyć przygotowaną instrukcję i wykonać go trzy razy z innym wiązaniem parametrów. Zapewnia to lepszą wydajność niż trzy pojedyncze instrukcje i uniemożliwia wykonywanie iniekcji SQL.
  • Można zaprojektować jeden-na-wszystkie zapytania jak to czy cokolwiek z Unią:

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

Jeśli teraz pomyśleć „co ten facet mówi?To już nie będzie atomowa. "Wtedy powinieneś użyć transakcji ...

+0

"To już nie będzie atomowe." - multi_query nie jest atomowe albo – johannes

+0

@johannes: tak, ale możesz pomyśleć, że –

+0

Dlatego właśnie wyjaśniłem :-) – johannes

Powiązane problemy