关于mysql:在PHP中使用PDO,如何检查最终的SQL参数化查询?

In PHP with PDO, how to check the final SQL parametrized query?

本问题已经有最佳答案,请猛点这里访问。

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

是否有方法检查数据库真正执行的操作?


所以我想我最终会回答我自己的问题,以便有一个完整的解决方案。但必须感谢本·詹姆斯和凯拉什·巴杜,他们提供了这方面的线索。

简短的回答
正如本·詹姆斯所说:不。
PHP端不存在完整的SQL查询,因为带有标记的查询和参数分别发送到数据库。仅在数据库端存在完整查询。

即使试图创建一个函数来替换PHP端的令牌,也不能保证替换过程与SQL过程相同(像令牌类型、bindValue与bindParam等复杂的东西)。

解决方法
我在这里详细阐述了Kailash Badu的答案。通过记录所有SQL查询,我们可以看到服务器上真正运行的是什么。使用MySQL,可以通过更新my.cnf(在我使用wamp服务器的情况下是my.ini)并添加如下行来完成此操作:

1
log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

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


将准备好的语句与参数化的值一起使用并不是动态创建SQL字符串的另一种方法。在数据库中创建一个准备好的语句,然后单独发送参数值。

因此,发送到数据库的可能是PREPARE ...,然后是SET ...,最后是EXECUTE ...

您将无法获得一些像SELECT * FROM ...这样的SQL字符串,即使它会产生同等的结果,因为实际上从未向数据库发送过这样的查询。


您可能可以使用PDOStatement->debugDumpParams。请参阅PHP文档。


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


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

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

1
SET GLOBAL general_log = 'ON';

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

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

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

1
>ps auxww|grep [m]ysqld

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

1
2
3
4
5
6
$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();

因为它创造了:

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

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

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

得到

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

完成后,执行:

1
SET GLOBAL general_log = 'OFF';

否则你的日志会变大。


最简单的方法是读取mysql执行日志文件,并且可以在运行时执行。

这里有一个很好的解释:

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


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

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

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

其中:
$column是我的代币
$param是分配给token的实际值
$this->fullStmt是我用替换的代币打印的唯一声明。

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

我希望我没有把你搞糊涂,至少给你指明了正确的方向。


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

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


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