2012-07-16 91 views
5

是否可以导出格式为mysqli::prepare::bind_param的查询?从“mysqli->准备”导出“查询”

实施例:

<?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 

有没有解决方法?

谢谢。

回答

6

我知道这对调试很有用,但它不是准备语句的工作方式。参数不与客户端上的预备语句组合。 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。

+0

其实也许对“mysql的”侧面的东西是解决方案(不完全你的答案),但还是不知道如何做这个实用的方法。 – 2013-06-14 21:15:20

+0

我不相信MySQL有这样的内置任何东西。你总是可以使自己的prepare()函数来做到这一点。 – Anonymous 2013-06-15 14:06:49

-1

你可以只手动重申回声行的查询字符串,并将字符串中的变量像这样:

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; 
    }; 
} 

多,你发布的评论中指出你的问题其实是:

How to show the last queries executed on MySQL?

+0

这不是一个解决方案。它不适用于“逃生”。部分使用“bind_param”的想法是为了安全。请编辑你的答案。 – 2013-06-14 21:13:22

+1

为了公平起见,您的问题显示您希望打印出查询,但您没有提及您想要导出的内容。 _“使用”bind_param“的部分想法是为了安全。”_您要求从准备好的语句中导出查询并将其打印出来,我向您提供了一个合适的替代方案来导出打印您的查询。如果你的项目需要你做别的事情,那么你的问题应该反映出来,所以你可以收到适当的回应。没有,我编辑了我的解决方案,并添加了您应该阅读的类似问题。 – varubi 2013-06-15 18:56:35

+1

感谢您的帮助。阅读@ BillKarwin的答案:http://stackoverflow.com/questions/11508752/export-query-from-mysqli-prepare/17098261#17098261可能会帮助你理解问题的建议。 – 2013-06-18 14:28:15

0

准备好的语句不会像那样工作,这是您无法看到语句的原因,因为它应该能够在没有操作的情况下传递到数据库。

所以唯一的解决办法就是将数据附加到你的字符串,并回显或保存到变量。

编辑,包括对你评论的安全问题..

//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(); 
    } 
+0

这不是一个解决方案。它不适用于“逃生”。部分使用“bind_param”的想法是为了安全。请编辑你的答案。 – 2013-06-14 21:11:26

+0

只要在mysql_real_escape_string ....就像上面那样 – KyleK 2013-06-14 21:19:22

+1

你最好说: “最好不要使用bind_param,使用mysqli_query + mysql_real_escape_string”。你同意吗?无论如何谢谢你的帮助。 – 2013-06-14 21:23:16