150

在 PHP 中,当使用带有参数化查询的 PDO 访问 MySQL 数据库时,如何检查最终查询(在替换所有令牌之后)?

有没有办法检查数据库真正执行了什么?

4

9 回答 9

58

所以我想我最终会回答我自己的问题,以便为记录提供完整的解决方案。但必须感谢 Ben James 和 Kailash Badu 提供了线索。

简短的回答
正如本詹姆斯所说:
PHP 端不存在完整的 SQL 查询,因为 query-with-tokens 和参数是分开发送到数据库的。只有在数据库端才存在完整的查询。

即使尝试在 PHP 端创建一个替换标记的函数也不能保证替换过程与 SQL 相同(棘手的东西,如标记类型、bindValue 与 bindParam,...)

解决方法
这是我详细说明 Kailash Badu 的答案的地方。通过记录所有 SQL 查询,我们可以看到服务器上真正运行的内容。使用 mySQL,这可以通过更新 my.cnf(或我的 Wamp 服务器中的 my.ini)来完成,并添加如下行:

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

只是不要在生产中运行它!!!

于 2009-11-28T21:20:37.060 回答
34

您也许可以使用PDOStatement->debugDumpParams. 请参阅PHP 文档

于 2009-12-13T05:46:37.250 回答
30

使用带有参数值的预处理语句不仅仅是动态创建 SQL 字符串的另一种方式。您在数据库中创建准备好的语句,然后单独发送参数值。

所以可能发送到数据库的内容将是一个PREPARE ...,然后是SET ...最后EXECUTE ...

SELECT * FROM ...即使会产生等效的结果,您也无法获得类似的 SQL 字符串,因为实际上从未将此类查询发送到数据库。

于 2009-11-23T22:17:33.603 回答
10

我检查查询日志以查看作为准备好的语句执行的确切查询。

于 2009-11-25T01:49:20.427 回答
4

我最初避免打开日志记录来监视 PDO,因为我认为这会很麻烦,但一点也不难。您不需要重新启动 MySQL(5.1.9 之后):

在 phpMyAdmin 或您可能具有高 db 权限的任何其他环境中执行此 SQL:

SET GLOBAL general_log = 'ON';

在终端中,跟踪您的日志文件。我的在这里:

>sudo tail -f /usr/local/mysql/data/myMacComputerName.log

您可以使用以下终端命令搜索您的 mysql 文件:

>ps auxww|grep [m]ysqld

我发现PDO逃避一切,所以你不能写

$dynamicField = 'userName';
$sql = "SELECT * FROM `example` WHERE `:field` = :value";
$this->statement = $this->db->prepare($sql);
$this->statement->bindValue(':field', $dynamicField);
$this->statement->bindValue(':value', 'mick');
$this->statement->execute();

因为它创建:

SELECT * FROM `example` WHERE `'userName'` = 'mick' ;

这没有产生错误,只是一个空的结果。相反,我需要使用

$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value";

要得到

SELECT * FROM `example` WHERE `userName` = 'mick' ;

完成后执行:

SET GLOBAL general_log = 'OFF';

否则你的日志会变得很大。

于 2013-04-12T06:46:28.487 回答
1

我为打印该实际查询所做的工作有点复杂,但它有效:)

在将变量分配给我的语句的方法中,我有另一个看起来有点像这样的变量:

$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt);

其中:
$column是我的令牌
$param是分配给令牌的实际值
$this->fullStmt是我的带有替换令牌的仅打印语句

它所做的只是在真正的 PDO 分配发生时用值替换标记。

我希望我没有使您感到困惑,并且至少为您指明了正确的方向。

于 2009-11-23T22:38:11.150 回答
1

最简单的方法是读取 mysql 执行日志文件,您可以在运行时执行此操作。

这里有一个很好的解释:

如何显示在 MySQL 上执行的最后一个查询?

于 2015-05-06T19:55:32.723 回答
0

我不相信你可以,尽管我希望有人会证明我错了。

我知道您可以打印查询,它的 toString 方法将向您显示没有替换的 sql。如果您正在构建复杂的查询字符串,这可能会很方便,但它不会为您提供带有值的完整查询。

于 2009-11-23T22:03:21.017 回答
-1

我认为使用 pdo 时查看最终查询文本的最简单方法是生成特殊错误并查看错误消息。我不知道该怎么做,但是当我在使用 pdo 的 yii 框架中出现 sql 错误时,我可以看到查询文本

于 2013-06-04T11:39:02.283 回答