Ниже приведен подход, который не только улучшит качество ваших сообщений об ошибках, но и улучшит работу с вашими наборами результатов.
$q["Orders"]="SELECT * FROM orders WHERE location = 'IN' ORDER BY orderNum DESC LIMIT 20";
$q["Inventory"]="SELECT * FRO inventory";
if(!$link=mysqli_connect("host","user","pass","db")){
echo "Failed to connect to MySQL: ",mysqli_connect_error();
}elseif(mysqli_multi_query($link,implode(';',$q))){
do{
$q_key=key($q); // current query's key name (Orders or Inventory)
if($result=mysqli_store_result($link)){ // if a result set... SELECTs do
while($row=mysqli_fetch_assoc($result)){ // if one or more rows, iterate all
$rows[$q_key][]=$row;
}
mysqli_free_result($result);
echo "<div><pre>"; // <pre> is for easier array reading
var_export($rows[$q_key]);
echo "</pre></div>";
}
} while(next($q) && mysqli_more_results($link) && mysqli_next_result($link));
}
if($mysqli_error=mysqli_error($link)){ // check & declare variable in same step to avoid duplicate func call
echo "<div style=\"color:red;\">Query Key = ",key($q),", Query = ",current($q),", Syntax Error = $mysqli_error</div>";
}
Ошибка при первом запросе: Если ваш первый запрос пытается получить доступ к таблице, которая не существует в выдвинутой базе данных, как: ordersXYZ
массива $rows
не будет существовать, не var_export()
не произойдет, и вы будет видеть этот ответ:
Запрос ключ = заказов, запросов = SELECT * FROM ordersXYZ WHERE расположение = 'В' ORDER BY orderNum DESC LIMIT 20, Ошибка синтаксиса = Таблица '[someDB] .ordersXYZ' не существует
Ошибка на втором запросе: Если ваш первый запрос успешен, но ваш второй запрос пытается получить доступ к несуществующей таблице, как: inventory2
$rows["Orders"]
проведет необходимые данные строки и будет var_export()
«эд , $row["Inventory"]
не будет существовать, и вы увидите этот ответ:
Query Key = Inventory, Query = SELECT * FROM inventory2, Синтаксис Error = Таблица '[someDB] .inventory2' не существует
Нет ошибок: Если оба запроса являются безошибочным, ваш $rows
массив будет заполнен нужными данными и var_export()
«под ред, и не будет никакого ответа ошибки. С запрошенными данными, сохраненными в $rows
, вы можете получить доступ к тем, что вы хотите от $rows["Orders"]
и $rows["Inventory"]
.
Things отметить:
Вы можете заметить, что я делаю объявление переменного и условные проверки в то же время, это делает код более DRY.
Как мой подход использует implode()
с точкой с запятой на линии elseif
, не забудьте добавить к вашим запросам конечную полуточку.
Этот набор запросов всегда возвращает набор результатов, потому что все являются запросами SELECT, если у вас есть смешанная коллекция запросов, которые affect_rows
, вы можете найти полезную информацию по этой ссылке (https://stackoverflow.com/a/22469722/2943403).
mysqli_multi_query()
прекратит выполнение запросов, как только появится ошибка. Если вы ожидаете, что поймаете «все» ошибки, вы обнаружите, что их никогда не будет больше одного.
Написание условных точек останова, как в вопросе и решении OP, нецелесообразно. В то время как пользовательские точки останова могут быть правильно использованы в других обстоятельствах, для этого случая точки останова должны быть расположены внутри инструкции while()
блока do()
.
Запрос, возвращающий нулевые строки, не вызовет сообщение об ошибке - он просто не создаст никаких подмассивов в $rows
, потому что цикл while()
не будет введен.
С помощью функции key()
можно избежать условия if/elseif
OP, которое подсчитывает столбцы в каждой строке набора результатов. Это лучшая практика, потому что выполнение условий на каждой итерации может стать дорогостоящим в некоторых случаях. Обратите внимание, что указатель массива продвигается внутри $q
в конце каждой итерации do()
. Это дополнительный метод, который вы не найдете на странице руководства php; он позволяет работать key()
.
И, конечно, линии <div><pre>var_export()...</pre></div>
можно удалить из рабочего кода - это было чисто для демонстрации.
Если вы собираетесь запускать больше запросов после этого кода, чтобы повторно использовать переменные, обязательно очистите все используемые переменные, чтобы остаточные данные не мешали. например $mysqli_error=null; // clear errors
& reset($q); // reset array pointer
.
Берегись это несколько расплывчатым предупреждения на свое усмотрение: http://php.net/manual/en/mysqli.use-result.php:
Не следует использовать mysqli_use_result(), если много обработки на стороне клиента выполняется, так как это будет подвязать сервер и предотвращают обновление других потоков от любых таблиц, из которых извлекаются данные .
Наконец и ГЛАВНОГО по соображениям безопасности, не отображать запрос или ошибку запроса информации публично - вы не хотите, зловещие люди, чтобы увидеть этот вид обратной связи. Не менее важно, всегда защищайте свои запросы от инъекционных хаков.Если ваши запросы включают данные, предоставленные пользователем, вам необходимо отфильтровать/дезинформировать данные до смерти, прежде чем использовать их в mysqli_multi_query()
. На самом деле, имея дело с пользовательским вводом, моя очень сильная рекомендация - отойти от mysqli_multi_query()
и использовать либо prepared statements, либо pdo для взаимодействия с базой данных для более высокого уровня безопасности.
Хороший комментарий. Это не приведет к ошибке в первом запросе. – David
Конечно, вам нужно проверить возвращаемые значения всех функций, что означает mysqli_multi_query и mysqli_store_result для первого запроса, а mysqli_next_result для всех остальных. – rx80