2012-07-16 89 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