В PHP с PDO, как проверить окончательный параметризованный запрос SQL?

В PHP, когда вы получаете доступ к базе данных MySQL с помощью PDO с параметризованным запросом, как вы можете проверить окончательный запрос (после замены всех токенов)?

Есть ли способ проверить, что действительно выполняется базой данных?

9 ответов

Решение

Поэтому я, наконец, отвечу на свой вопрос, чтобы получить полное решение для записи. Но надо поблагодарить Бена Джеймса и Кайлаша Баду, которые предоставили подсказки для этого.

Короткий ответ
Как отметил Бен Джеймс: НЕТ.
Полный запрос SQL не существует на стороне PHP, так как запрос с токенами и параметры отправляются отдельно в базу данных. Только на стороне базы данных полный запрос существует.

Даже попытка создать функцию для замены токенов на стороне PHP не гарантирует, что процесс замены будет таким же, как в SQL (хитрые вещи, такие как тип токенов, bindValue против bindParam,...)

Временное решение
Здесь я уточняю ответ Кайлаша Баду. Регистрируя все SQL-запросы, мы можем видеть, что действительно выполняется на сервере. В случае с MySQL это можно сделать, обновив my.cnf (или my.ini в моем случае с Wamp-сервером) и добавив следующую строку:

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

Только не запускайте это в производство!!!

Вы могли бы использовать PDOStatement->debugDumpParams, Смотрите документацию по PHP.

Использование подготовленных операторов с параметризованными значениями - это не просто еще один способ динамического создания строки SQL. Вы создаете подготовленный оператор в базе данных, а затем отправляете только значения параметров.

Так что то, что, вероятно, отправлено в базу данных, будет PREPARE ..., затем SET ... и наконец EXECUTE ...,

Вы не сможете получить некоторую строку SQL, например SELECT * FROM ...даже если он даст эквивалентные результаты, потому что такой запрос фактически никогда не отправлялся в базу данных.

Я проверяю журнал запросов, чтобы увидеть точный запрос, который был выполнен как подготовленный оператор.

Изначально я избегал включать ведение журнала для мониторинга PDO, потому что думал, что это будет хлопотно, но это совсем не сложно. Вам не нужно перезагружать MySQL (после 5.1.9):

Выполните этот SQL в phpMyAdmin или любой другой среде, где у вас могут быть высокие привилегии БД:

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';

иначе ваши журналы станут огромными.

То, что я сделал, чтобы напечатать этот фактический запрос, немного сложнее, но он работает:)

В методе, который присваивает переменные моему утверждению, у меня есть другая переменная, которая выглядит примерно так:

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

Куда:
$column мой знак
$param фактическое значение, присваиваемое токену
$this->fullStmt мое заявление только для печати с замененными токенами

Он просто заменяет токены значениями, когда происходит реальное назначение PDO.

Надеюсь, я вас не смутил и, по крайней мере, указал вам правильное направление.

Самый простой способ сделать это - прочитать файл журнала выполнения mysql, и вы можете сделать это во время выполнения.

Здесь есть хорошее объяснение:

Как показать последние запросы, выполненные на MySQL?

Я не верю, что вы можете, хотя я надеюсь, что кто-то докажет, что я неправ.

Я знаю, что вы можете напечатать запрос, и его метод toString покажет вам sql без замен. Это может быть удобно, если вы строите сложные строки запроса, но не дает полного запроса со значениями.

Я думаю, что самый простой способ увидеть окончательный текст запроса при использовании pdo - это сделать специальную ошибку и посмотреть сообщение об ошибке. Я не знаю, как это сделать, но когда я делаю ошибку SQL в фреймворке yii, который использует pdo, я мог видеть текст запроса

Другие вопросы по тегам