【发布时间】:2011-01-19 05:24:25
【问题描述】:
我正在努力学习在 PHP 中使用准备好的语句和 mysqli,通常,如果我在查询时遇到问题,我只需将其回显到屏幕上,第一步看看它的样子。
如何使用准备好的语句做到这一点?
我想看看变量被替换后的 SQL 语句。
【问题讨论】:
我正在努力学习在 PHP 中使用准备好的语句和 mysqli,通常,如果我在查询时遇到问题,我只需将其回显到屏幕上,第一步看看它的样子。
如何使用准备好的语句做到这一点?
我想看看变量被替换后的 SQL 语句。
【问题讨论】:
使用准备好的语句:
在 PHP 端没有“构建” SQL 查询,因此无法实际获取该查询。
这意味着如果您想查看 SQL 查询,则必须使用 SQL 查询,而不是准备好的语句。
【讨论】:
var_dump 应该已经可以帮助您查看发送到 MySQL 服务器的数据。
对于使用 mysql_stmt_prepare() 和 mysql_stmt_execute() C API 函数执行的预处理语句,服务器将 Prepare 和 Execute 行写入一般查询日志,以便您知道语句何时准备和执行。
[...] 服务器将以下行写入通用查询日志:
准备 [1] SELECT ?
执行 [1] 选择 3
因此,出于调试目的,请激活 general log 并密切关注该文件。
编辑:哦,这个问题有一个 [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 上。
【讨论】:
...) 在函数中简化此操作
我最近更新了这个项目,包括作曲家集成、单元测试和更好地处理通过引用接受参数(这需要更新到 php 5.6)。
我创建了一组扩展默认 mysqli 和 mysqli_stmt 类的类,以允许您查看潜在查询字符串的再现,这应该提供您正在寻找的内容:
https://github.com/noahheck/E_mysqli
这是您普通mysqli 对象的(接近)直接替换,当您prepare() 查询字符串时返回自定义mysqli_stmt 对象。绑定参数后,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 = 'john.doe@example.com'
使用此扩展有一些注意事项(在 github 项目的 README 中进行了解释),但是对于解决应用程序的麻烦区域,或从程序转换到面向对象的样式,这应该为大多数人提供一定程度的帮助用户。
正如我在 github 项目中所述,我没有任何使用 mysqli 扩展的实际经验,并且该项目是应其姊妹项目用户的要求创建的,因此可以提供任何反馈非常感谢在生产中使用它的开发人员。
免责声明 - 正如我所说,我做了这个扩展。
【讨论】:
同意 Pascal MARTIN (+1),因此我建议使用另一种调试技术:var_dump() 或记录您插入语句中的每个变量,这样您应该能够确定它是错误数据还是逻辑错误错误的 SQL。
【讨论】:
您可以使用Lottip 之类的工具。这个想法就像 MySQL 代理一样。它解析 MySQL 数据包,提取查询及其参数,因此您可以查看准备好的语句及其内容。
【讨论】: