我们使用Doctrine,一个PHP ORM。我创建了一个这样的查询:

$q = Doctrine_Query::create()->select('id')->from('MyTable');

然后在函数中,我添加了各种where子句和适当的东西,像这样

$q->where('normalisedname = ? OR name = ?', array($string, $originalString));

稍后,在execute()-ing该查询对象之前,我想打印出原始SQL以检查它,并这样做:

$q->getSQLQuery();

但是,这只打印准备好的语句,而不是完整的查询。我想看看它正在发送什么到MySQL,但相反,它正在打印一个准备好的语句,包括?是否有一些方法可以看到'full'查询?


当前回答

没有其他真正的查询,这就是预处理语句的工作方式。这些值绑定在数据库服务器中,而不是应用程序层。

看到我对这个问题的回答:在PHP与PDO,如何检查最终的SQL参数化查询?

(为了方便起见,这里重复一遍:)

使用带参数化值的准备语句不仅仅是动态创建SQL字符串的另一种方法。在数据库中创建一个准备好的语句,然后单独发送参数值。 所以发送到数据库的可能是一个PREPARE…,然后SET…最后执行.... 你将无法获得一些SQL字符串,如SELECT * FROM…,即使它会产生相同的结果,因为没有这样的查询实际上发送到数据库。

其他回答

我已经创建了一个Doctrine2 Logger,它就是这样做的。它使用Doctrine 2自己的数据类型转换器将参数化sql查询与值“水合”起来。

<?php


namespace Drsm\Doctrine\DBAL\Logging;
use Doctrine\DBAL\Logging\SQLLogger,
    Doctrine\DBAL\Types\Type,
    Doctrine\DBAL\Platforms\AbstractPlatform;
/**
 * A SQL logger that logs to the standard output and
 * subtitutes params to get a ready to execute SQL sentence

 * @author  dsamblas@gmail.com
 */
class EchoWriteSQLWithoutParamsLogger implements SQLLogger

{
    const QUERY_TYPE_SELECT="SELECT";
    const QUERY_TYPE_UPDATE="UPDATE";
    const QUERY_TYPE_INSERT="INSERT";
    const QUERY_TYPE_DELETE="DELETE";
    const QUERY_TYPE_CREATE="CREATE";
    const QUERY_TYPE_ALTER="ALTER";

    private $dbPlatform;
    private $loggedQueryTypes;
    public function __construct(AbstractPlatform $dbPlatform, array $loggedQueryTypes=array()){
        $this->dbPlatform=$dbPlatform;
        $this->loggedQueryTypes=$loggedQueryTypes;
    }
    /**
     * {@inheritdoc}
     */
    public function startQuery($sql, array $params = null, array $types = null)

    {
        if($this->isLoggable($sql)){
            if(!empty($params)){
                foreach ($params as $key=>$param) {
                    $type=Type::getType($types[$key]);
                    $value=$type->convertToDatabaseValue($param,$this->dbPlatform);
                    $sql = join(var_export($value, true), explode('?', $sql, 2));
                }

            }
            echo $sql . " ;".PHP_EOL;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function stopQuery()
    {

    }
    private function isLoggable($sql){
        if (empty($this->loggedQueryTypes)) return true;
        foreach($this->loggedQueryTypes as $validType){
            if (strpos($sql, $validType) === 0) return true;
        }
        return false;
    }
}

使用例子:; 下面的代码将在标准输出中返回使用$em实体管理器生成的任何INSERT,UPDATE,DELETE SQL语句,

/**@var  \Doctrine\ORM\EntityManager $em */
$em->getConnection()
                ->getConfiguration()
                ->setSQLLogger(
                    new EchoWriteSQLWithoutParamsLogger(
                        $em->getConnection()->getDatabasePlatform(),
                        array(
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_UPDATE,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_INSERT,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_DELETE
                        )
                    )
                );

你可以检查你的应用执行的查询,如果你把所有的查询都记录在mysql中:

http://dev.mysql.com/doc/refman/5.1/en/query-log.html

会有更多的查询,不仅是一个你正在寻找,但你可以grep它。

->getSql();作品

编辑:

查看我使用的所有mysql查询

sudo vim /etc/mysql/my.cnf 

加上这两行:

general_log = on
general_log_file = /tmp/mysql.log

重新启动mysql

编辑2 如果你没有找到mysql的配置(它可以在很多地方),只需从mysql命令行设置这些变量。

mysql -u root -p 

SHOW VARIABLES LIKE 'general_log_file';
SHOW VARIABLES LIKE 'general_log';

SET GLOBAL general_log = 'on';
SET GLOBAL general_log_file = '/tmp/mysql.log';

//view the queries
sudo tail -f /tmp/mysql.log

这些设置的生命周期直到MySQL重新启动。或者是笔记本电脑。所以他们不是永久的-这在我看来是伟大的-我只需要他们当我调试时,我不需要担心编辑配置然后删除他们。如果您不删除日志记录,如果您忘记它,它可能会增长太多。

要打印出Doctrine中的SQL查询,请使用:

$query->getResult()->getSql();

我为这个主题做了一些研究,因为我想调试生成的SQL查询并在SQL编辑器中执行它。从所有的答案中可以看出,这是一个技术性很强的话题。

当我假设最初的问题是基于dev-env时,目前缺少一个非常简单的答案。您可以只使用Symfony profiler中的构建。只需点击Doctrine标签,滚动到你想检查的查询。然后点击“查看可运行查询”,你可以直接在SQL编辑器中粘贴你的查询

更多的UI基础方法,但非常快,没有调试代码开销。

您可以使用以下方法轻松地访问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(:?)中的参数通常是一个嵌套数组。

同时,如果你找到了其他方法,请与我们分享:)

谢谢你!