[英]Why is mysqli giving a "Commands out of sync" error?
我正在尝试运行以下内容。
<?php
$db = mysqli_connect("localhost","user","pw") or die("Database error");
mysqli_select_db($db, "database");
$agtid = $_POST['level'];
$sql = sprintf("call agent_hier(%d)", $agtid);
$result = mysqli_query($db, $sql) or exit(mysqli_error($db));
if ($result) {
echo "<table border='1'>
<tr><th>id</th>
<th>name</th>
<th>parent_id</th>
<th>parent_name</th>
<th>level</th>
<th>email</th></tr>";
while ($row = mysqli_fetch_assoc($result))
{
$aid = $row["id"];
$sql2 = "SELECT * FROM members WHERE MEMNO = '$aid'";
$result2 = mysqli_query($db,$sql2) or exit(mysqli_error($db));
while ($newArray = mysqli_fetch_array($result2)) {
$fname = $newArray['FNAME'];
$lname = $newArray['LNAME'];
$mi = $newArray['MI'];
$address = $newArray['ADDRESS'];
$city = $newArray['CITY'];
$state = $newArray['STATE'];
$zip = $newArray['ZIP'];
$kdate = $newArray['KDATE'];
$date = abs(strtotime(date('m/d/Y')) - strtotime(date($kdate))) / (60 * 60 * 24);
}
echo sprintf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
$row["id"],$row["name"],
$row["parent_id"],$row["parent_name"],
$row["level"],$row["email"]);
}
echo "</table>";
}
mysqli_free_result($result);
mysqli_close($db);
?>
如果我从以下位置删除行:
$aid = $row["agent_id"];
到....
$date = abs(strtotime(date('m/d/Y')) - strtotime(date($kdate))) / (60 * 60 * 24);
}
一切都会好起来的。 如果没有,我会收到以下错误:
命令不同步; 你现在不能运行这个命令
在研究中,我认为这可能是由于多个 MySQLi 查询同时运行,其中使用mysqli_multi_query
但对于指南中的所有示例和一般数据似乎并不适用。
有任何想法吗?
MySQL 客户端不允许您在仍有要从正在进行的查询中提取的行的情况下执行新查询。 有关常见错误,请参阅 MySQL 文档中的命令不同步。
您可以使用mysqli_store_result()
从外部查询中预取所有行。 这将在 MySQL 客户端中缓冲它们,因此从服务器的角度来看,您的应用程序已获取完整的结果集。 然后,即使在从现在缓冲的外部结果集中获取行的循环中,您也可以执行更多查询。
或者您使用mysqli_result::fetch_all()
返回完整的结果集作为 PHP 数组,然后您可以遍历该数组。
调用存储过程是一种特殊情况,因为存储过程有可能返回多个结果集,每个结果集都可能有自己的一组行。 这就是为什么@a1ex07 的答案提到使用mysqli_multi_query()
并循环直到mysqli_next_result()
没有更多结果集。 这对于满足 MySQL 协议是必要的,即使在您的情况下,您的存储过程只有一个结果集。
PS:顺便说一下,我看到您正在执行嵌套查询,因为您有表示层次结构的数据。 您可能需要考虑以不同方式存储数据,以便更轻松地查询数据。 我做了一个关于这个标题为Models for Hierarchical Data with SQL and PHP的演讲。 我还在我的书SQL 反模式:避免数据库编程的陷阱 的一章中介绍了这个主题。
下面是如何在 CodeIgnitor 3.0.3 中实现mysqli_next_result()
:
system/database/drivers/mysqli/mysqli_driver.php
262行改
protected function _execute($sql)
{
return $this->conn_id->query($this->_prep_query($sql));
}
对此
protected function _execute($sql)
{
$results = $this->conn_id->query($this->_prep_query($sql));
@mysqli_next_result($this->conn_id); // Fix 'command out of sync' error
return $results;
}
自 2.x 以来,这一直是一个问题。 我刚刚更新到 3.x,不得不将这个 hack 复制到新版本。
只需调用此函数:
$this->free_result();
function free_result() {
while (mysqli_more_results($this->conn) && mysqli_next_result($this->conn)) {
$dummyResult = mysqli_use_result($this->conn);
if ($dummyResult instanceof mysqli_result) {
mysqli_free_result($this->conn);
}
}
}
简单地说,您必须在调用 mysqli_free_result 之后调用 mysqli_next_result($db) 。
mysqli_free_result($result); mysqli_next_result($db) mysqli_close($db);
您必须关闭存储过程保持的先前连接。 您无需每次都关闭连接,只需使用:
mysqli_next_result($conn);
对于新的 mariaDb,请检查 in_predicate_conversion_threshold 参数。 默认情况下,您最多可以为“In”查询使用 1000 个属性
如果您还对存储过程进行了几次调用,并面临上述错误,那么韦恩先生,我为您提供了一个解决方案。
恕我直言,在某处,对Stored Procedure
的CALL
实际上弄乱了连接。 所以你所要做的就是重置数据库连接句柄。
你甚至可以在你的配置文件中有一个函数来为你做这件事,你所做的就是在对Stored Procedure
进行任何query
或CALL
之前调用该函数一次
我的实现是(忽略$app
因为我正在研究它在那里的silex
框架,YMMV)
function flushhandle() {
global $app;
global $db_host;
global $db_user;
global $db_pass;
global $db_name;
$app['mysqlio']->close();
$app['mysqlio'] = new mysqli($db_host, $db_user, $db_pass, $db_name);
return $app['mysqlio'];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.