【问题标题】:Export "query" from "mysqli->prepare"从“mysqli->prepare”导出“query”
【发布时间】:2012-07-16 16:44:09
【问题描述】:

是否可以导出mysqli::prepare::bind_param格式的查询?

例子:

<?php
$mysqli = new mysqli('host', 'user', 'pass', 'table');
if(mysqli_connect_errno()){
    printf('Connect failed: %s\n', mysqli_connect_error());
    exit;
}

$data=7290;

if ($stmt = $mysqli->prepare('SELECT `id`,`info` FROM `propertys` WHERE id>?')){
    $stmt->bind_param('i',$data);
    $stmt->execute();
    $stmt->bind_result($id,$info);
    while($q=$stmt->fetch()){
        echo $id,': ',$info,'<br>';
    }
    $stmt->close();
}
$mysqli->close();
?>

我想导出mysql::preparebind_param 执行的QUERY 函数 所以(这是一个虚构的例子):

if ($stmt = $mysqli->prepare('SELECT `id`,`info` FROM `propertys` WHERE id>?')){
    $stmt->bind_param('i',$data);
    $stmt->execute();
    echo $stmt->exportQuery();//Function does not exist, just for example

函数::exportQuery 会这样打印:

SELECT `id`,`info` FROM `propertys` WHERE id>7290

有什么解决办法吗?

谢谢。

【问题讨论】:

    标签: php mysqli prepared-statement


    【解决方案1】:

    我知道这对调试很有用,但这不是准备好的语句的工作方式。参数不与客户端上的准备好的语句组合。 PHP 永远不应访问与其参数组合的查询字符串。

    执行prepare()时将SQL语句发送到数据库服务器,执行execute()时单独发送参数。 MySQL 的通用查询日志确实显示了最终的 SQL,其中包含在您执行 () 之后插入的值。以下是我的一般查询日志的摘录。我从 mysql CLI 运行查询,而不是从 PHP,但原理是一样的。

    081016 16:51:28 2 Query       prepare s1 from 'select * from foo where i = ?'
                    2 Prepare     [2] select * from foo where i = ?
    081016 16:51:39 2 Query       set @a =1
    081016 16:51:47 2 Query       execute s1 using @a
                    2 Execute     [2] select * from foo where i = 1
    

    你的评论:

    @Baily 是正确的,MySQL 没有客户端解决方案来返回插入参数的完整查询。这不是 PHP 的错。

    要启用我上面提到的日志记录,请在 MySQL 客户端中使用此命令,或者通过 API 从 PHP 提交:

    SET GLOBAL general_log = ON;
    

    您应该在收集完信息后关闭日志,因为记录每个查询确实需要一些开销。

    SET GLOBAL general_log = OFF;
    

    PS:动态更改日志记录设置需要 MySQL 5.1 或更高版本。在早期版本中,更改日志记录时必须重新启动 mysqld。

    【讨论】:

    • 实际上也许“mysql”方面的一些东西是解决方案(不完全是你的答案),但仍然不知道如何做到这一点。
    • 我不相信 MySQL 有这样的内置功能。您可以随时创建自己的 prepare() 函数来执行此操作。
    【解决方案2】:

    准备好的语句不是这样工作的,你看不到语句是有原因的,因为它应该能够在不进行操作的情况下传递到数据库。

    因此,唯一的解决方案是将数据附加到字符串,然后回显或保存到变量。

    编辑以包含您评论的安全问题..

    //Assume you're using $_GET to get the id
    $data = mysql_real_escape_string($_GET['yourID']);
    
    $yourStatement = 'SELECT `id`,`info` FROM `propertys` WHERE id>';
    $savedStatement = $yourStatement.$data;
    
    echo $savedStatement;
    //Will return 'SELECT `id`,`info` FROM `propertys` WHERE id>4'
    
    if ($stmt = $mysqli->prepare($yourStatement.'?')){
    $stmt->bind_param('i',$data);
    $stmt->execute();
      }
    

    【讨论】:

    • 这不是解决方案。它不适用于“逃脱”。使用“bind_param”的部分想法是为了安全。请编辑您的答案。
    • 你最好说:“最好不要使用bind_param,使用mysqli_query+mysql_real_escape_string”。你同意吗?无论如何,谢谢你的帮助。
    • 这是一个技巧问题吗?你在寻求帮助吗?还是只是测试人?
    • 不用客气,但你不明白提问的目的。是不是更接近正确答案:stackoverflow.com/questions/11508752/… 或许能帮助你理解问题。
    • 我不是故意粗鲁,我真的很想知道,如果这就是问题的目的:)
    【解决方案3】:

    您可以在回显行上重复查询字符串,然后手动将变量放入字符串中,如下所示:

    if ($stmt = $mysqli->prepare('SELECT `id`,`info` FROM `propertys` WHERE id>?')){
        $stmt->bind_param('i',$data);
        if($stmt->execute()){
            echo 'SELECT `id`,`info` FROM `propertys` WHERE id>'.$data;
        };
    }
    

    您发布的大部分 cmets 表明您的问题实际上是:

    How to show the last queries executed on MySQL?

    【讨论】:

    • 这不是解决方案。它不适用于“逃生”。使用“bind_param”的部分想法是为了安全。请编辑您的答案。
    • 公平地说,您的问题显示您想要打印查询,您没有提及您希望导出执行的其他操作。 “使用“bind_param”的部分想法是出于安全考虑。” 您要求从准备好的语句中导出查询并将其打印出来,我为您提供了一个合适的替代方法来导出打印您的查询。如果您的项目需要您做其他事情,那么您的问题应该反映这一点,以便您可以收到适当的回复。没有,我编辑了我的解决方案并添加了一个您应该阅读的类似问题。
    • 感谢您的帮助。阅读@BillKarwin 的回答:stackoverflow.com/questions/11508752/… 可以帮助您理解问题的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2011-07-12
    • 2012-10-04
    • 2010-10-30
    • 2018-08-11
    • 2011-10-13
    相关资源
    最近更新 更多