微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对不同的查询使用相同的 mysqli 准备语句?

如何解决对不同的查询使用相同的 mysqli 准备语句?

通过一些测试;一个小问题出现了。当我通常编写数据库更新时;我通常通过我在 PHP 中编码的回调来做到这一点;我只是将给定的 mysqli connection object 作为函数参数传递给它。事实证明,在同一单个连接上执行所有查询(例如三个查询)比为给定查询序列的每个查询关闭和重新打开数据库连接要快得多。这也适用于 sql 事务,连接可以毫无问题地传递给回调。

我的问题是;你也可以用 prepared statement objects 做到这一点吗?我的意思是,考虑到我们成功建立了一个 $conn 对象,代表 MysqLi 连接,这样的东西合法吗? :

function select_users( $users_id,$stmt ) {

  $sql = "SELECT username FROM users where ID = ?";

  MysqLi_stmt_prepare( $stmt,$sql );
  MysqLi_stmt_bind_param( $stmt,"i",$users_id );
  MysqLi_stmt_execute( $stmt );

  return MysqLi_stmt_get_result( $stmt );

}

function select_labels( $artist,$stmt ) {

  $sql = "SELECT label FROM labels where artist = ?";

  MysqLi_stmt_prepare( $stmt,"s",$artist );
  MysqLi_stmt_execute( $stmt );

  return MysqLi_stmt_get_result( $stmt );

}

$stmt = MysqLi_stmt_init( $conn );

$users = select_users( 1,$stmt );
$rappers = select_labels( "rapperxyz",$stmt );

或者这是不好的做法;你应该使用:

$stmt_users = MysqLi_stmt_init( $conn );
$stmt_rappers = MysqLi_stmt_init( $conn );

$users = select_users( 1,$stmt_users );
$rappers = select_labels( "rapperxyz",$stmt_rappers );

测试期间;我注意到该方法通过使用沿回调传递的单个语句对象适用于服务器调用,其中我通过 4 个连续的回调调用了 4 个不太复杂的数据库查询

然而,当我使用 10 个不同的查询进行服务器调用时,有时(是的,只是有时;对于在不同执行中使用的几乎相同的数据;所以这对我来说似乎是奇怪的行为)我收到错误 { {1}} 和其他一些我从未遇到过的奇怪错误,例如变量数量与参数数量不匹配;尽管他们在检查完所有内容后都做得很好。经过一些研究,我发现解决这个问题的唯一方法确实是为每个回调使用不同的语句对象。所以,我只是想知道;你真的应该总是为一个查询使用一个准备好的语句对象,然后你可以连续执行 N 次吗?

解决方法

是的。

“命令不同步”错误是因为 MySQL 协议不像 http。您无法随时发送请求。服务器端(即 mysqld)有一个状态期待特定的请求序列。这就是所谓的有状态协议。

与 ftp 之类的协议进行比较。您可以在 ftp 客户端中执行 ls,但您返回的文件列表取决于当前工作目录。如果您在应用程序中的多个函数之间共享该 ftp 客户端连接,则您不知道另一个函数没有更改工作目录。因此,您无法确定从 ls 获得的文件列表是否代表您认为所在的目录。

在 MySQL 中,服务器端也有状态。您一次只能打开一笔交易。一次只能执行一个查询。 MySQL 客户端不允许您在仍有要从正在进行的查询中提取的行的情况下执行新查询。有关常见错误,请参阅 MySQL 文档中的 Commands out of sync

因此,如果您将语句句柄传递给某些回调函数,那么该函数如何知道执行该语句是安全的?

IMO,使用语句的唯一安全方法是立即使用它。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。