如何查看查询中的参数?
Posted
技术标签:
【中文标题】如何查看查询中的参数?【英文标题】:How do I view the parameters in a query? 【发布时间】:2012-06-28 21:05:33 【问题描述】:为了调试我的代码,我想查看执行的显式 sql 查询。
我使用createQueryBuilder
创建查询,我实现的最明确的事情是使用原始查询:
$qb->getQuery()->getSQL();
问题是,我看到的不是参数,而是持有者 (?
)。
我在网上找到了一些解决方案,但它们适用于 1.3 和 1.4,不适用于 Symfony-2。
想法?谢谢!
【问题讨论】:
其实你的问题是这个***.com/q/2095394/795876的重复。 Doctrine 正在使用准备好的语句,因此 php 端从来没有“真正的”SQL 查询,Doctrine 无法显示它。但是,您可以阅读此解决方案 ***.com/a/10577703/795876 以进行调试。 另外,学说 2 有 sqlLogger 类:doctrine-orm.readthedocs.org/en/2.0.x/reference/… fsehat - 看起来这个解决方案适用于 Symfony 1.4,我在整个项目中既找不到getSqlQuery
函数也找不到 getFlattenedParams
(这是我失踪了)。 manix - 你有更多关于如何在 Symfony 2.x 中使用记录器的参考资料吗?它看起来像一个很好的解决方案,但我没有找到任何好的文档。 谢谢你们!
【参考方案1】:
您可以使用$query->getParameters()
访问占位符使用的参数,因此您可以使用以下方法调试您的查询:
$query = $qb->getQuery();
print_r(array(
'sql' => $query->getSQL(),
'parameters' => $query->getParameters(),
));
【讨论】:
基本上这是个好主意。问题是参数包可能包含对象,然后尝试打印它会给出巨大的字符串。我想做的是将$query->getParameters()
返回的参数包转换为可以替换占位符?
的字符串数组。
我认为这个数组已经是一个标量值数组,如果你看一下 setParameter 方法 github.com/doctrine/doctrine2/blob/2.2/lib/Doctrine/ORM/… ,它会调用将数组和对象转换为标量值的 processParameterValue github.com/doctrine/doctrine2/blob/2.2/lib/Doctrine/ORM/…
有趣的是,我得到了(据我所知......)所有供应商的最后一个版本,而我的 AbstractQuery.php
和 Query.php
有点不同。可能我拥有的是 Doctrine 2.1,而这段代码是 2.2。无论如何,我在Query.php
文件中添加了一个方法,该方法根据您的回答返回原始 sql + 参数。谢谢!
据我所知,您可以取回的数据远不如您输入的有用。getSQL()
显示?
占位符,即使您使用了:namedPlaceholders
。 getParamaters()
没有说明它与这些占位符的关系。使用 3 个占位符和两个键/对(在语句中重用一个参数)的语句,你怎么知道要在哪里插入什么值?【参考方案2】:
您可以使用以下方法轻松访问 SQL 参数。
$result = $qb->getQuery()->getSQL();
$param_values = '';
$col_names = '';
foreach ($result->getParameters() as $index => $param)
$param_values .= $param->getValue().',';
$col_names .= $param->getName().',';
//echo rtrim($param_values,',');
//echo rtrim($col_names,',');
所以如果你把$param_values
和$col_names
打印出来,就可以得到通过sql传递的参数值和各自的列名。
注意:如果$param
返回一个数组,则需要重新迭代,因为IN (:?)
里面的参数通常是嵌套数组。
同时,如果您发现了另一种方法,请与我们分享 :)
谢谢!
【讨论】:
【参考方案3】:我必须建立一个 requete union(使用 DQL 或 QueryBuilder 不可能),其中已经使用 QueryBuilder 构建了 5 个查询。所以我重用了这些查询,但我在使用 getParameters() 函数时遇到了问题,因为它以与你给出的相同顺序给出参数。使用查询构建器的优点之一是您可以按您想要的顺序创建查询,但是当您检索参数时,您可能会在检索时混乱。 为避免这种情况,我构建了以下功能:
$getSqlWithParams = \Closure::bind(function()
return [$this->getSql(), $this->processParameterMappings($this->_parserResult->getParameterMappings())];
, null, Query::class);
现在当你想要检索 sql 和你做的排序参数时:
$getSqlWithParams()->call($query)
不要忘记使用 \Doctrine\ORM\Query 语句。 瞧!
【讨论】:
【参考方案4】:我还一直在寻找一种从 DQL 查询中获取参数注入 SQL 的方法,以帮助调试,例如,允许我输出一个可以直接粘贴到 phpmyadmin 中的 SQL 字符串,并为其添加说明等。
无论如何,我的答案基于 Néo 的答案,由于私有方法调用,我无法让它工作,我通过在 Doctrine\ORM\Query 中创建一个函数来进行调整,如下所示:
/**
* Execute query and return the SQL with params injected.
*
* @return string
* @throws QueryException
*/
public function executeAndGetSqlWithParams(): string
// Execute the query to get the parser result.
$this->execute();
// Declare the SQL for use in the vsprintf function.
$sql = str_replace('?', '%s', $this->getSQL());
// Declare the SQL parameter mappings.
$parameterMappings = $this->processParameterMappings($this->_parserResult->getParameterMappings());
/**
* TODO: Possibly replace each question mark by the correct vsprintf argument using $parameterMappings[1].
*
* Right now all parameters are treated as strings.
*/
// Declare and define the SQL parameters.
$sqlParameters = [];
foreach ($parameterMappings[0] as $parameter)
if (is_array($parameter))
$sqlParameters[] = implode(',', $parameter);
else
$sqlParameters[] = $parameter;
// Return the SQL with its parameters injected.
return vsprintf($sql, $sqlParameters);
顾名思义,它执行查询以从解析器结果中获取参数映射,然后将其与 vsprintf 一起使用以将参数替换为其值。
这当然是对核心代码的破解,由于我不熟悉为公共项目做出贡献,如果有人想尝试将其包含在其中,请随意复制。
【讨论】:
【参考方案5】:我会在 SQL Server 中使用 Profiler 来获取发送到数据库的内容。显然,mysql 也有一些类似的工具。 Is there a Profiler equivalent for MySql?
【讨论】:
以上是关于如何查看查询中的参数?的主要内容,如果未能解决你的问题,请参考以下文章