我使用的准备方法如下:
$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->errno
返回0,这表示没有出现任何问题。但是,prepare方法失败并返回false,因此我无法检查$stmt->error;
我偶然发现,当我删除第一个$stmt->execute()
调用时,再次调用prepare方法可以正常工作(在其第一次和第二次调用时)。我在这里错过了什么?
编辑
根据Maxim Tkach的建议,如果我取消注释
// $stmt->close();
然后我得到
成功
成功
但为什么呢?我从来没有在任何地方读到过结束一个准备发言是至关重要的。
这来自PHP手册:
关闭准备好的语句。mysqli_stmt_close()还解除分配语句句柄。如果当前对账单有挂起或未读结果,此函数将取消它们,以便可以执行下一个查询已执行。
我看不出他们说为了执行第二份准备声明而结束是至关重要的。我是不是错过了什么?
您需要阅读以下内容:准备好的报表
prepared语句执行由两个阶段组成:prepared和处决在准备阶段,一个语句模板被发送到数据库服务器。服务器执行语法检查并初始化供以后使用的服务器内部资源。
和
每个准备好的语句都占用服务器资源。声明应使用后立即显式关闭。如果没有明确地进行,当语句句柄被释放时,该语句将被关闭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的检查返回值并执行-这将是好的
您需要读取$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);
}
...