Living
Chaplin

Wayne Zheng

PHP PDO参数绑定查询后,查看实际执行SQL的方法

2016-04-11 13:43
php

PDO提供了一个PDOStatement::debugDumpParams — 打印一条 SQL 预处理命令的调试方法,但是打印出来的结果有点鸡肋,比如说:

<?php
try {
    $pdo = new PDO();

    $sql = "SELECT * FROM `users` WHERE `username` = ? AND `email` = ?";
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(1, $username, PDO::PARAM_STR);
    $stmt->bindParam(2, $email, PDO::PARAM_STR);
    $username = 'wynnezheng';
    $email = '********@qq.com';
    $stmt->execute();
    
    $stmt->debugDumpParams();
} catch (PDOException $e) {
    echo $e->getMessage();
}

// 结果很感人:
// SQL: [58] SELECT * FROM `users` WHERE `username` = ? AND `email` = ?
// Params:  2
// Key: Position #0:
// paramno=0
// name=[0] ""
// is_param=1
// param_type=2
// Key: Position #1:
// paramno=1
// name=[0] ""
// is_param=1
// param_type=2
?>

要是 SQL 语句一复杂这根本就阅读不了嘛!

PDO 的执行方式的不同,导致SQL 语句并不是在参数绑定上去后再传入数据库服务器的,上面的这段代码它在内部的执行方式是这样的:

<?php
// $stmt = $pdo->prepare($sql); 
prepare sql from 'SELECT * FROM `users` WHERE `username` = ? AND `email` = ?' 

// $username = 'wynnezheng';
// $email = '********@qq.com';
// $stmt->bindParam(1, $username, PDO::PARAM_STR);
// $stmt->bindParam(2, $email, PDO::PARAM_STR);
set @username = 'wynnezheng'
set @email = '********@qq.com'

// $stmt->execute();
execute sql using @username, @email
?>

可以看到,PDO 的执行在 mysql 中其实是分步进行的,因此 PDO 并没有办法去获取到绑定参数后完整的 SQL 语句

当然还是有解决的调试方法的,就是通过 mysql 日志来查看所有的数据库查询,以下是在windows平台,通过 mysql 控制台来设置(也可以通过 mysql my.ini 配置文件来设置):

# 查看日志情况
# show variables like '%general%';

# 开启日志
# SET GLOBAL general_log = 'On';

# 指定日志文件
# SET GLOBAL general_log_file = 'E:/my.log';

再执行一遍刚刚额查询,就可以在E:/my.log中看到以下的内容了:

160411 13:26:27     4 Connect   root@localhost on mall
            4 Query SELECT * FROM `users` WHERE `username` = 'wynnezheng' AND `email` = '********@qq.com'
            4 Quit