Prepared语句使命令不同步;你可以';t现在不要运行此命令


Prepared Statement getting Commands out of sync; you can't run this command now

我已经阅读了我能想到的所有内容来获得解释,但似乎没有任何帮助。如果有人能够指出显而易见的地方,或者让我稍微了解一下问题所在。我已经通读了php.net和mysqli标记,似乎不明白这一点。我读到的所有内容都说你不能发送两个查询,但我只尝试了一个。任何帮助都将不胜感激。

这个->https://stackoverflow.com/a/9649149/1626329-表示我可能有多个结果集,但我不确定这有多大意义,也不确定我能做些什么来获得更多关于准备好的语句内部工作的细节。

我的代码:

class mydb {
    public function __construct() {
        // Connect to Database
        $this->mydb = new mysqli('****', '***', '***', '***');
        if ($this->mydb->connect_errno) { // Error on connection failure
            echo "Failed to connect to MySQL in Construct: (" . $this->mydb->connect_errno . ") " . $this->mydb->connect_error;
        }
    }
    public function choose ($select, $from, $config = 0, $options = NULL) {
        if ($config === 0) { /** Configure statement for prepare depending on options */
            $stmt = 'SELECT ' . $select . ' FROM ' . $from;
        } elseif ($config === 1) {
            $stmt = 'SELECT ' . $select . ' FROM ' . $from . ' WHERE ' . $options['where_comp'] . ' LIKE ?';
        } elseif ($config === 2) {
            $stmt = 'SELECT ' . $select . ' FROM ' . $from . ' WHERE ' . $options['where_comp'] . ' = ?';
        } /** End if/elseif Prepare statemenet */
        $mydb = $this->mydb->prepare($stmt);
        if ($config === 1 || $config === 2) {
            $mydb->bind_param("s",$options['where_value']);
        }
        if ($mydb->execute()) { /** If execute is good then get results */
            $result = $mydb->get_result();
            $payload = array();
            while ($row = $result->fetch_array(MYSQLI_NUM)) {
                $payload[] = $row;
            }
            return $payload;
        } /** End if results */
    } /** End choose class method */
} /** End mydb Class */
$myDB = new mydb();
$agentArray = $myDB->choose('*','`agent`');

使用php.net示例并对其进行了修改,以显示更好的示例:

$mysqli = new mysqli('host', 'database', 'user', 'pass');
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
if (!($stmt = $mysqli->prepare("SELECT ? FROM ?"))) {
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
if (!$stmt->execute()) {
    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!($res = $stmt->get_result())) {
    echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;
}
for ($row_no = ($res->num_rows - 1); $row_no >= 0; $row_no--) {
    $res->data_seek($row_no);
    var_dump($res->fetch_assoc());
}
$res->close();

本页"相关"部分的第一个结果(意味着它是在你写问题时提供给你的)提供了一个解决方案。

一般来说,根据错误消息很容易找到问题的答案。你所需要的只是不要停留在第一个搜索结果上,而是多做一点。

但是,在您的函数choose()上。我发现它非常不切实际,不安全,而且毫无用处:

  • 不切实际,因为它不允许您使用SQL,而是它的一个非常有限的子集。
    • 而且它还使您的代码极难理解
  • 不安全,因为它没有为所有动态部件提供保护,但仅在有价值的地方
  • 没用,因为它可以为你节省不多的钱

看,你以为你省了两个字——SELECTFROM

 $agentArray = $myDB->choose('*','`agent`',1,
               array('where_comp' => 'name', 'where_value' -> "%bob%"));

然而,您使这些代码难以理解,难以维护,也无法运行最简单的JOIN。为什么不做呢?更不用说实际的代码比传统的SQL查询长:

$sql = 'SELECT * FROM `agent` WHERE name LIKE ?';
$agentArray = $myDB->query($sql, "%bob%");

哪一个更容易阅读?

添加一个if语句来正确显示错误实际上会给出一个可以使用的mysql错误响应:

if (!($stmt = $mysqli->prepare("SELECT ? FROM ?"))) {
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

错误响应:Prepare failed: (1064) You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1

--您不能通过准备好的语句传递标识符,应该只将其用于从用户输入传递的值。