【问题标题】:PHP Prepare method not working when calling it twice?PHP Prepare方法在调用两次时不起作用?
【发布时间】:2016-05-11 13:36:53
【问题描述】:

我使用的prepare方法如下:

$db= new mysqli("localhost","***","***","***");

if ($db->connect_error) {
  die('Connection Error');
}

$id = 1;
if($stmt = $db->prepare('SELECT name FROM table WHERE id = ? '))
{
  $stmt->bind_param('i', $id);
  $stmt->execute();
  // $stmt->close();
  echo "Success<br>";
}
else {
  echo "Something broke :/<br>";
}

$id =2;
if($stmt = $db->prepare('SELECT name FROM table WHERE id = ? '))
{
  $stmt->bind_param('i', $id);
  $stmt->execute();
  echo "Success<br>";
}
else {
  echo "Something broke :/<br>";
  $error = $db->errno . ' ' . $db->error;
  echo $error;
}

如果我执行我得到的脚本

成功

东西坏了:/

0

在第二次调用 prepare 方法后,我如何找出它失败的原因?出于某种原因,$db-&gt;errno 返回 0,表示没有出错。但是,prepare 方法失败并返回 false,所以我无法检查 $stmt-&gt;error;

我偶然发现,当我删除第一个 $stmt-&gt;execute() 调用时,再次调用 prepare 方法可以正常工作(在第一次和第二次调用时)。我在这里错过了什么?

编辑

如果我取消注释,Maxim Tkach 建议

// $stmt->close();

然后我得到

成功

成功

但这是为什么呢?我从未在任何地方读到关闭准备语句至关重要。

这是来自 PHP 手册:

关闭一个准备好的语句。 mysqli_stmt_close() 也会释放 语句句柄。如果当前语句有待处理或未读 结果,此函数将它们取消,以便可以进行下一个查询 执行。

我没有看到他们说关闭以执行第二个准备语句至关重要。我错过了什么吗?

【问题讨论】:

  • if(!$stmt-&gt;execute()){ trigger_error("There was an error.... ".$db-&gt;error, E_USER_WARNING);} ?这就是问题所在吗?可能还有php.net/manual/en/function.error-reporting.php
  • @Fred-ii- 不,我在调用 bind_param 方法时已经收到错误。
  • 你到底想对亚当做什么?我想我没有抓住这个问题。你能详细说明一下吗?您是否需要记录错误并准确捕获导致错误的原因?如果是这样,那么您应该查看日志。等待其他人看看他们是否对您的问题有更好的理解。
  • 我还是不知道这个问题是关于什么的; 对不起
  • foreach loop 之外为prepare statement 写入,在foreach loop. 内部为bind_param and execute statemen 写入

标签: php


【解决方案1】:

您需要阅读:Prepared Statements

准备好的语句执行包括两个阶段:准备和 执行。在准备阶段,一个语句模板被发送到 数据库服务器。服务器执行语法检查并初始化 服务器内部资源供以后使用。

每个准备好的语句都会占用服务器资源。声明应 使用后立即明确关闭。如果没有明确完成, 当语句句柄被释放时,语句将被关闭 PHP。

看完这篇文章,我总结道: 如果不关闭前一个查询,则无法准备查询。始终准备好在执行后关闭查询

你的代码应该改写如下:

$db= new mysqli("localhost","***","***","***");
if ($db->connect_error) {   
      die('Connection Error'); 
}
$id = 1; 
if($stmt = $db->prepare('SELECT name FROM table WHERE id = ? ')) { 
      $stmt->bind_param('i', $id);   
      $stmt->execute(); 
      echo "Success<br>"; 
} else {   
       echo "Something broke :/<br>"; 
}

$id = 2;
$stmt->bind_param('i', $id); 
$stmt->execute();
$stmt->close();   

P.S如果加上bind和execute的check返回值就好了

【讨论】:

    【解决方案2】:

    你需要阅读 $stmt->error;

    要阅读,您需要重写代码,如下例所示。

    ...
    $stmt = new mysqli_stmt($db);
    if($stmt->prepare('SELECT name FROM table WHERE id = ? '))
    {
      $stmt->bind_param('i', $id);
      $stmt->execute();
      echo "Success<br>";
    }
    else {
      var_dump($stmt->error);
    }
    ...
    

    【讨论】:

    • 如果准备语句失败,则返回 false。所以我不能在 else 子句中访问$stmt-&gt;error,因为它是一个布尔值。但是我只是注意到,如果我在$id=2 之后调用$stmt = new mysqli_stmt($db),那么我的第二个准备语句不会失败。仍然 - 我不知道为什么第二个准备好的语句在我的脚本中失败以及如何访问错误消息。
    • 也许你需要调用 $stmt->close();在第一次请求之后?
    • 你是对的,如果我在第一次请求后调用$stmt-&gt;close() 它可以工作(但是,我不需要预先初始化 $stmt)。但为什么?我在手册中没有发现关闭准备语句是强制性的。我调整了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多