【问题标题】:Nested prepared statements and free_result嵌套准备好的语句和 free_result
【发布时间】:2022-01-27 03:19:05
【问题描述】:

有人可以解释为什么 free_result 在嵌套准备语句的 while 循环后导致 bind_result 没有按预期更新值吗?

$stmt = $mysqli -> prepare("select col1 from table1 inner join ...");
$stmt -> bind_param("i", $id);
$stmt -> bind_result($col1);
$stmt -> execute() or die();
$stmt -> store_result();

$stmt2 = $mysqli -> prepare("select col2, col3 from table2 where col4 = ?");
$stmt2 -> bind_param("i", $col1);
$stmt2 -> bind_result($col2, $col3);

while ($stmt -> fetch()) {
    $stmt2 -> execute() or die();
    $stmt2 -> store_result();
    while ($stmt2 -> fetch()) {
        echo $col2 .",";
    }
    $stmt2 -> free_result(); // <== Works fine without this line
    echo "---";
}
$stmt -> close();
$stmt2 -> close();

如果我删除 free_result,我会得到预期的输出,比如说:

1,2,---3,4,5,---6,7,---

如果我离开它,父循环上第一次运行的最后一个结果会像这样重复:

1,2,---2,2,2,---2,2,---

我在docs 中找不到答案...这似乎违反直觉,因为结果被保留而不是被释放。

这是一个可执行文件example

【问题讨论】:

  • 如果将整个$stmt2 分组移动到while 循环中会发生什么? IE。 preparebind_parambind_result?附带说明一下,由于性能原因,在循环中执行 SQL 语句可能会出现问题。你到底想做什么?
  • @waterloomatt 它工作正常,但我不知道为什么。此外,这意味着该语句将与父循环运行的次数一样多。一个应用程序是:用户查找订单,每个订单可能包含多个产品、多个付款等... PHP 逻辑更复杂,以处理接收到的数据。我有一些应用程序,使用嵌套语句维护起来会容易得多。所以我试图理解为什么free_result 会导致问题。
  • 看起来很有趣,如果它有适当的 MCVE,我会调查的。虽然我可以为你创建一个 MCVE,但对于我的一生,我不明白为什么它应该是一个帮助的人的负担,而不是一个寻求帮助的人
  • @YourCommonSense 同意。我在帖子中添加了一个示例。

标签: php mysql mysqli prepared-statement


【解决方案1】:

bind_result() 的文档中所述:

必须在 mysqli_stmt_execute() 之后和调用 mysqli_stmt_fetch() 之前绑定所有列。

如果您将bind_result() 调用移动到适当的位置,它将起作用:

$stmt = $mysqli->prepare("select col1 from table1");
$stmt->execute();
$stmt->bind_result($col1);
$stmt->store_result();

$stmt2 = $mysqli->prepare("select col2, col3 from table2 where col4 = ?");
$stmt2->bind_param("i", $col1);

while ($stmt->fetch()) {
    $stmt2->execute();
    $stmt2->bind_result($col2, $col3);
    $stmt2->store_result();
    while ($stmt2->fetch()) {
        echo $col2 .",";
    }
    $stmt2->free_result();
    echo "---";
}
$stmt->close();
$stmt2->close();

原因是mysqli_stmt::free_result() 要求mysqlnd 释放所有结果变量。引用被释放,但变量和它们的值都不会被 PHP 破坏。它们只是不受约束。

您可以停止使用mysqli_stmt::free_result()(您可能无论如何都应该这样做)或在每次执行后绑定结果变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    相关资源
    最近更新 更多