这是一种方法,不仅可以提高错误消息的质量,还可以改进处理结果集的方式。
$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>" . var_export($rows[$q_key], true) . "</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 location='IN' ORDER BY orderNum DESC LIMIT 20,语法错误 = 表 '[someDB].ordersXYZ' 不存在
第二个查询错误:如果您的第一个查询成功,但您的第二个查询尝试访问不存在的表,例如:inventory2
$rows["Orders"]
将保存所需的行数据并将被var_export()
'ed,$row["Inventory"]
将不存在,您将看到以下响应:
查询键 = Inventory,查询 = SELECT * FROM inventory2,语法错误 = 表 '[someDB].inventory2' 不存在
没有错误:如果两个查询都没有错误,您的$rows
数组将填充所需的数据并var_export()
'ed,并且不会有错误响应。将查询的数据保存在 中,您可以从和$rows
中访问您想要的内容。$rows["Orders"]
$rows["Inventory"]
注意事项:
您可能会注意到我同时进行变量声明和条件检查,这使代码更加简洁,但一些开发人员更愿意避免这种情况。
由于我的方法在行implode()
上使用分号,因此请elseif
确保不要在查询中添加尾随分号。
这组查询总是返回一个结果集,因为所有查询都是 SELECT 查询,如果您有混合的查询集合,您可以在此链接 ( https://stackoverflow.com/a/22469722/2943403 )affect_rows
找到一些有用的信息。
mysqli_multi_query()
一旦出现错误,将立即停止运行查询。如果您期望捕获“所有”错误,您会发现永远不会超过一个。
不建议像在 OP 的问题和解决方案中那样编写条件断点。虽然在其他情况下可能会正确使用自定义断点,但在这种情况下,断点应位于块的while()
语句内部。do()
返回零行的查询不会导致错误消息——它只是不会在其中创建任何子数组,$rows
因为while()
不会进入循环。
通过使用该函数,可以避免计算每个结果集行中的列key()
的 OP条件。if/elseif
这是更好的做法,因为在某些情况下,在每次迭代中运行条件可能会变得很昂贵。请注意,数组指针在每次迭代$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()
并使用mysqli或pdo准备好的语句来进行数据库交互,以获得更高级别的安全性。