2016-05-02 33 views
1

我試圖使用多個準備好的語句與PHP和mysqli驅動程序並獲得了臭名昭著的錯誤:如何關閉mysqli prepared語句中的結果集,但保留語句 - 不緩衝整個結果?

Commands out of sync; you can't run this command now

雖然我覺得這個數據庫API是殘暴腦損傷,我不明白爲什麼我得到錯誤,如this question所述。

幾種解決方案都提供在這個和其他各種答案,我發現周圍鋪設,是我見過的唯一的,似乎工作涉及

$stmt->store_result() 

其緩衝整個結果集。

但是,我不想緩衝整個結果集 - 我想放棄它,而不使用(大量的)內存來存儲它!

所有我想做的事情,就是創建一份聲明中,使用bind_param()bind_result()fetch()得到一些結果,然後以某種方式關閉的結果,這樣我可以再次使用statment並運行其他查詢直到那時

我已經試過了從聲明中獲取實際結果對象的所有方法,並明確地關閉了它,並且我試過調用next_result()直到它返回null。這些解決方案都不能防止出現該錯誤。

那麼,如何關閉結果集並在fetch()之後執行其他準備好的語句,而不廢棄執行的語句並且不得不重新解析查詢?

$q = $dbc->prepare("SELECT id, typename, storageclass, tablename FROM _dbtype WHERE typename=?"); 
$q->bind_param("s", $typeName); 
$q->bind_result($id,$typeName,$storageClass,$tableName); 
$q->execute(); 
$q->fetch(); // ie. only once 
... <something that does not destroy $q> ... 
$q2 = $dbc->prepare("SELECT id, name FROM _storagetype"); 
+0

如果你不得不爲每個準備好的語句創建一個不同的連接,它會讓我大吃一驚。沒有其他數據庫我使用過,強迫你做任何非高性能和愚蠢的事情...... =/ – BadZen

回答

1

看到mysqli_stmt::free_result()
(和http://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-free-result.html的暗示, 「如果有打開的語句的遊標,mysql_stmt_free_result()關閉它。」)

<?php 
mysqli_report(MYSQLI_REPORT_STRICT|MYSQLI_REPORT_ALL); 
$mysqli = new mysqli('localhost', 'localonly', 'localonly', 'test'); 
if ($mysqli->connect_errno) { 
    trigger_error(sprintf('mysqli connect error (%d) %s', $mysqli->connect_errno, $mysqli->connect_error), E_USER_ERROR); 
    die; 
} 
$mysqli->query('CREATE TEMPORARY TABLE sofoo (id int auto_increment, primary key(id))'); 
$mysqli->query('INSERT INTO sofoo VALUES(),(),(),(),(),()'); 


$stmtA = $mysqli->prepare('SELECT id FROM sofoo WHERE id>1'); 
$stmtB = $mysqli->prepare('SELECT id FROM sofoo WHERE id<10 ORDER BY id DESC'); 


$stmtA->execute(); 
$stmtA->bind_result($id); 
$stmtA->fetch(); echo $id, PHP_EOL; 
$stmtA->free_result(); // without this the script ends with "Fatal error: Uncaught mysqli_sql_exception: Commands out of sync;" 

$stmtB->execute(); 
$stmtB->bind_result($id); 
$stmtB->fetch(); echo $id, PHP_EOL; 

如果有多個結果集(即如果你必須使用next_result()),你必須分別爲每個結果集調用free_result()

+0

啊,謝謝!我甚至沒有考慮過這個函數,因爲文檔引發了我:「釋放與mysqli_stmt_store_result()分配的語句相關的結果內存」。所以,我認爲這隻適用於'store_result()'!。似乎工作,但是! – BadZen