mysqli函数库支持prepared语句的使用。它们对于在执行大量具有不同数据的相同查询时,可以提高执行速度。它们也可以免受SQL注射风格(injection-style)的攻击。
Prepared语句的基本思想是可以向MySQL发送一个需要执行的查询模板,然后再单独发送数据。我们可以向相同的Prepared语句发送大量的相同数据;这个特性对批处理的插入操作来说是非常有用的。
在insert_book.php脚本中,可以使用prepared语句,如下所示:
$query="insert into books values(?,?,?,?)";
$stmt=$db->prepare($query);
$stmt->bind_param("sssd",$isbn,$author,$title,$price);
$stmt->execute;
echo$stmt->affected_rows.'book inserted into database.';
$stmt->close;
下面,我们逐行分析以上代码。
当设置查询时,不是替换前面已经生成的变量,而是在每一段数据的位置设置问号。在这些问号的周围,不能再设置问号或其他分界符号。
第二行是调用$db->prepare,在过程版本中,是通过mysqli_stmt_prepare函数实现的。这一行将构建一个语句对象或需要用来完成实际处理的资源。
语句对象有一个bind_param方法。(在过程版本中,是mysqli_stmt_bind_param函数)。bind_param的用途是告诉PHP哪些变量应该被问号所替换。第一个参数是一个格式化字符串,与printf使用的格式化字符串不同。在这里,所传递的值意味着4个参数分别是字符串、字符串、字符串和双精度。格式化字符串中的其他可能字符还有:i表示整数,b表示blob。在这个参数之后,必须列出与语句中的问号数量相同的变量。它们将依次被替换。
调用$stmt->execute函数(在过程版本中是mysqli_stmt_execute函数)将真正运行这个查询。我们可以访问受影响的行数并关闭这个语句。
那么Prepared语句的作用如何呢?这里,一个优点是可以改变这4个绑定变量的值,并且在不用准备的情况下重新执行这个语句。这个功能对于循环执行批量插入操作来说是非常有用的。
与绑定参数一样,也可以绑定结果。对于SELECT类型查询,可以使用$stmt->bind_result函数(或mysqli_stmt_bind_result函数)提供希望填充结果列的变量列表。
每次调用$stmt->fetch函数(或者mysqli_stmt_fetch函数)时,结果集下一行的列值将被填充到这些绑定变量中。例如,在前面介绍的图书搜索脚本中,可以使用:
$stmt->bind_result($isbn,$author,$title,$price);
将这4个变量绑定到将通过查询返回的4列。在调用如下语句后:
$stmt->execute;
可以在循环中调用:
$stmt->fetch;
每当该语句被调用时,它将获得下一个结果行,并填充到4个绑定变量中。
也可以在相同的脚本中使用mysqli_stmt_bind_param函数和mysqli_stmt_bind_result函数。