Как я могу просмотреть содержание подготовленного заявления?
Я работаю над тем, чтобы научиться использовать подготовленные инструкции с mysqli в PHP, и обычно, если у меня возникают проблемы с запросом, я просто выводю его на экран, чтобы посмотреть, как он выглядит в качестве первого шага.
Как я могу сделать это с помощью подготовленного заявления?
Я хотел бы увидеть инструкцию SQL после замены переменных.
6 answers
Используя подготовленные инструкции:
- Когда вы готовите инструкцию, она отправляется на сервер MySQL
- Когда вы связываете переменные + выполняете инструкцию, только переменные отправляются на сервер MySQL
- И оператор + связанные переменные выполняются на сервере MySQL - без повторного выполнения "подготовки" при каждом выполнении оператора (именно поэтому подготовленные операторы могут быть полезны для производительности, когда один и тот же оператор выполняется несколько раз раз)
На стороне PHP нет "построения" SQL-запроса, поэтому на самом деле нет способа получить этот запрос.
Это означает, что если вы хотите увидеть SQL-запрос, вы должны использовать, ну, SQL-запросы, а не подготовленные инструкции.
- Вы можете использовать PDOStatement->debugdumpparams, чтобы получить некоторую информацию о подготовленном операторе (в случае, если вы используете pdo).
- Подготовленные инструкции регистрируются в общем журнале MySQL:
Для подготовленных инструкций, которые выполняются с помощью функций API mysql_stmt_prepare() и mysql_stmt_execute() C, сервер записывает строки подготовки и выполнения в общий журнал запросов, чтобы вы могли определить, когда подготовлены инструкции и выполненный.
[...] сервер записывает следующие строки в общий журнал запросов:
Подготовить [1] ВЫБРАТЬ?
Выполнить [1] ВЫБЕРИТЕ 3
Поэтому в целях отладки активируйте общий журнал и следите за этим файлом.
Редактировать: о, у вопроса есть тег [mysqli]... полностью упущенный из виду.
Если оператор вообще не выполняется, проверили ли вы (дважды/трижды), что по пути не произошло ошибок?
echo "<pre>Debug: start</pre>\n";
$mysqli = new mysqli('localhost', 'localonly', 'localonly', 'test');
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
$result = $mysqli->query('CREATE TEMPORARY TABLE foo (id int auto_increment, x int, primary key(id))');
if ( false=== $result) {
die('error : '. $mysqli->error);
}
$stmt = $mysqli->prepare('INSERT INTO foo (x) VALUES (?)');
if ( false===$stmt ) {
die ('prepare() failed: ' . $mysqli->error);
}
$result = $stmt->bind_param('i', $x);
if ( false===$result ) {
die('bind_param() failed');
}
$x = 1;
$result = $stmt->execute();
if ( false===$result ) {
die('execute() failed: '.$stmt->error);
}
echo "<pre>Debug: end</pre>\n";
Я обычно делаю это, когда мне нужно отладить подготовленный sql с параметрами.
Пример подготовки и выполнения:
$sql = "SELECT VAL1, VAL2 FROM TABLE(?, '?', '?', '?', '?', ?, '?', '?', '?')";
$prep = ibase_prepare( $sql ) or die("Error");
$query = ibase_execute($prep, $param1, $param2, .....) or $err = true;
^^^^^^^^^^^^^^^^^^^^^^^
Простой способ отладки результирующего SQL предложения это:
printf( str_replace('?', '%s', $sql), $param1, $param2, ....);
^^^^^^^^^^^^^^^^^^^^^^
Вам нужно сделать только один printf, заменив? в подготовленной строке SQL на один %s. printf будет интерпретировать все как одну строку, принимая каждый параметр как размещающий его на каждом замененном %s.
Соглашаясь с Паскалем МАРТИНОМ (+1), поэтому я предлагаю другой метод отладки: var_dump()
или регистрируйте каждую переменную, которую вы вставляете в инструкцию, таким образом, вы сможете выяснить, являются ли это неверными данными или логически неправильным SQL.
Я недавно обновил этот проект, включив интеграцию с композитором, модульное тестирование и улучшив обработку принятия аргументов по ссылке (для этого требуется обновление до php 5.6).
Я создал набор классов, которые расширяют классы по умолчанию mysqli
и mysqli_stmt
, чтобы вы могли просматривать представление потенциальной строки запроса, которая должна предоставить то, что вы ищете:
Https://github.com/noahheck/E_mysqli
Это (близкое к) падение замена для вас обычного объекта mysqli
, который возвращает пользовательский объект mysqli_stmt
, когда вы prepare()
вводите строку запроса. После привязки ваших параметров E_mysqli
позволит вам просмотреть результирующую строку запроса как новое свойство объекта stmt
:
$mysqli = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName);
$query = "INSERT INTO registration SET name = ?, email = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $_POST['name'], $_POST['email']);
$stmt->execute();
echo $stmt->fullQuery;
Приведет к:
INSERT INTO registration SET name = 'John Doe', email = '[email protected]'
Есть некоторые предостережения при использовании этого расширения (описано в разделе README в проекте github), но для устранения неполадок в проблемных областях вашего приложения или перехода к объектно-ориентированному стилю с процедурной точки зрения это должно обеспечить определенный уровень помощи для большинства пользователей.
Как я описал в проекте github, у меня нет никакого практического опыта использования расширения mysqli
, и этот проект был создан по просьбе пользователей его дочернего проекта, поэтому любые отзывы, которые могут быть предоставлены разработчиками, использующими это в производстве, будут весьма признательны.
Отказ от ответственности - Как я уже сказал, я сделал это расширение.
Вы можете использовать такой инструмент, как Подсказка . Идея состоит в том, чтобы действовать как прокси-сервер MySQL. Он анализирует пакеты MySQL, извлекает запрос и его параметры, чтобы вы могли видеть подготовленные инструкции с его содержимым.