在准备好的语句上调用PDOStatement :: execute()时,有没有办法使原始SQL字符串执行?对于调试目的,这将非常有用。
我假设您的意思是您想要最终的SQL查询,并将参数值插入其中。我知道这对调试很有用,但是它不是准备好的语句的工作方式。参数不会在客户端与预准备的语句组合,因此PDO绝对不能访问与其参数组合的查询字符串。
当您执行prepare()时,SQL语句将发送到数据库服务器,而当您执行execute()时,将分别发送参数。MySQL的常规查询日志的确显示了最终SQL,其中包含在execute()之后插入的值。以下是我的一般查询日志的摘录。我从mysql CLI(不是从PDO)运行查询,但是原理是相同的。
081016 16:51:28 2 Query prepare s1 from 'select * from foo where i = ?' 2 Prepare [2] select * from foo where i = ? 081016 16:51:39 2 Query set @a =1 081016 16:51:47 2 Query execute s1 using @a 2 Execute [2] select * from foo where i = 1
如果您设置PDO属性PDO :: ATTR_EMULATE_PREPARES,则也可以获得所需的内容。在这种模式下,PDO将参数插值到SQL查询中,并在您执行execute()时发送整个查询。 这不是真正的准备查询。 通过在execute()之前将变量插值到SQL字符串中,可以避免准备查询的好处。
来自@afilina的评论:
否,文本SQL查询在执行期间 不会 与参数组合。因此,PDO没有任何东西可以向您显示。
在内部,如果您使用PDO :: ATTR_EMULATE_PREPARES,则PDO会在执行准备和执行之前复制SQL查询并向其中插入参数值。但是PDO不会公开此修改后的SQL查询。
PDOStatement对象具有属性$ queryString,但这仅在PDOStatement的构造函数中设置,并且在用参数重写查询时不会更新该属性。
对于PDO来说,要求他们公开重写的查询将是合理的功能请求。但是,除非您使用PDO :: ATTR_EMULATE_PREPARES,否则即使那样也不会给您“完整”的查询。
这就是为什么我显示了上面使用MySQL服务器的常规查询日志的解决方法的原因,因为在这种情况下,即使是带有参数占位符的准备好的查询也会在服务器上重写,并将参数值回填到查询字符串中。但这仅在日志记录期间完成,而不在查询执行期间完成。