2016-05-02 32 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