PDO、Mysql 和原生预处理语句

Posted

技术标签:

【中文标题】PDO、Mysql 和原生预处理语句【英文标题】:PDO, Mysql and native prepared statements 【发布时间】:2012-01-07 22:40:43 【问题描述】:

到目前为止,我对 PDO 的理解是,PDO 将在可能的地方使用真正的准备好的语句,并在不能的地方模仿它们。我也明白,就 mysql 而言,如果您正在与支持它们的 mysql 版本进行通信,那么将使用真正的准备好的语句。

事实上,MySQL PDO 驱动程序的 php 手册页说了这么多。 http://php.net/manual/en/ref.pdo-mysql.php

然而,在另一个我在How to replace all occurencies of char with elements from array? 上提供帮助的 SO 问题上,有人评论说这不是真的,实际上 PDO 在与 MySQL 数据库对话时模拟了准备好的语句。

我没有太多运气找到证据来支持那里提出的声明,但我确实发现有一个 PDO::ATTR_EMULATE_PREPARES 属性可以配置为切换准备好的语句模拟。

那么事情的真相是什么? PDO真的不使用mysql准备好的语句吗?如果不是,是否可以强迫它这样做,如果是,你应该这样做吗?我一直认为 mysql 有真正的准备好的语句,PDO 会使用它们,如手册中所述。说明书不准确吗?

编辑添加:我最近阅读了几篇文章,这些文章至少给出了一个很好的理由来说明为什么默认情况下会禁用真正的准备好的查询。 PHP 脚本的寿命往往很短,只能运行足够长的时间来生成对请求的响应,之后它们的所有资源都会被释放。对于每个请求只执行一次的任何查询,您实际上必须执行 2 个 SQL 命令(准备命令和执行命令),因此对于仅执行一次的任何准备好的语句,您实际上可能会比模拟的性能稍差准备好的声明。对于必须在循环中运行的查询,实际准备好的语句可能会执行得更好,但这种情况在 PHP 通常用于的请求/响应模型中相对较少。

我仍然认为真正的准备好的语句更可取,但至少我对为什么 PDO 默认使用模拟查询有一个合理的解释。

【问题讨论】:

【参考方案1】:

PDO真的不使用mysql的prepared statements吗?

是的,默认情况下(至少在我测试的版本中),但是可以手动打开原生模式。

如果不是,是否可以强制这样做

通过使用PDO::ATTR_EMULATE_PREPARES 设置,名称非常不言自明。

$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

你应该这样做吗?

这是所有问题中最难的问题。 好吧,我会说 - 是的,你应该。如果您选择 PDO 作为您的数据库驱动程序,那么在仿真模式下使用它是没有意义的。

【讨论】:

感谢您的回复。但是,它确实引出了一个问题,如果它支持它,那么为什么默认情况下它是关闭的? 我相信这是兼容性问题。

以上是关于PDO、Mysql 和原生预处理语句的主要内容,如果未能解决你的问题,请参考以下文章

PDO中的预处理

预处理语句

通过 PDO 扩展与 MySQL 数据库交互(下)

PHP操作PDO预处理以及事务

PHP操作PDO预处理以及事务

MySQL pdo预处理能防止sql注入的原因