mysqli::store_result

mysqli_store_result

(PHP 5, PHP 7, PHP 8)

mysqli::store_result -- mysqli_store_result转移上一次查询返回的结果集

说明

面向对象风格

mysqli::store_result ( int $option = ? ) : mysqli_result

过程化风格

mysqli_store_result ( mysqli $link , int $option = ? ) : mysqli_result

迁移 link 参数所指定的连接上的上一次查询返回的结果集, 迁移之后的结果集可以 在 mysqli_data_seek() 函数中使用。

参数

link

仅以过程化样式:由mysqli_connect()mysqli_init() 返回的链接标识。

option

指定的选项,可以是下列中的某一值:

Valid options
Name Description
MYSQLI_STORE_RESULT_COPY_DATA 将结果集从 mysqlnd 的内部缓冲区复制到 PHP 变量中。 默认情况下,mysqlnd 采取一种引用策略尽量避免在内容中复制多份同样的结果集。 例如,对于一个包含了很多行的结果集,每个行中的内容又不是很大,那么复制结果集的过程会导致内存使用率下降, 因为用来保存结果集数据的 PHP 变量可能提前被释放掉。 (此选项仅在使用 mysqlnd 驱动且 PHP 5.6.0 之后可用)。

返回值

成功则返回一个缓冲的结果集对象,失败则返回 false

Note:

如果上一查询并不产生结果集(例如,执行了一个 INSERT 语句), 那么 mysqli_store_result() 会返回 false。 如果读取结果集失败了,也会返回 false。 如何区分是上面哪种情况导致此函数的调用返回了 false? 你可以通过下面的方法来检测: mysqli_error() 返回了非空的字符串, mysqli_errno() 返回了非零值, 或者 mysqli_field_count() 返回了非零值, 都表示发生错误了。 还有一种可能的情况会导致此函数的调用返回 false:上一次查询 mysqli_query() 本身是成功的, 但是由于返回的结果集太大,无法为其分配足够的内存来进行结果集转移。 如果 mysqli_field_count() 函数返回了一个非零值,那么表示 SQL 语句产生了一个非空的结果集。

注释

Note:

执行查询之后, 使用 mysqli_free_result() 函数来释放结果集所占用的内存, 是一个很有用的实战经验。 尤其是当使用 mysqli_store_result() 函数来转移数量较大的结果集的时候, 释放结果集内存的操作尤为重要。

范例

See mysqli_multi_query().

参见

User Contributed Notes

filippo at ecoms dot it 18-Feb-2018 06:49
Code to handling errors:

if ($mysqli->multi_query($query)) {
    $result = $mysqli->store_result();
    if ($mysqli->errno == 0) {
   
        /* First result set or FALSE (if the query didn't return a result set) is stored in $result */

        while ($mysqli->more_results()) {
            if ($mysqli->next_result()) {
                $result = $mysqli->store_result();
                if ($mysqli->errno == 0) {
                    /* The result set or FALSE (see above) is stored in $result */
                }
                else {
                    /* Result set read error */
                    break;
                }
            }
            else {
                /* Error in the query */
            }
        }
    }
    else {
        /* First result set read error */
    }
}
else {
    /* Error in the first query */
}
Tex Morgan 06-Jul-2013 10:45
There's a simpler way to clear out database stored procedure problems:

class MySQLiQuery {
     protected $_resultSet;
     protected $databaseConnection;
....

    protected function free(){
        $this->_resultSet->free();
        $this->_resultSet=null;
    }

    protected function checkMoreResults(){
        if($this->databaseConnection->more_results()){
            return true;
        } else {
            return false;
        }
    }

    protected function clearResults(){
        if($this->checkMoreResults()){
            if($this->databaseConnection->next_result()){
                if($this->_resultSet=$this->databaseConnection->store_result()){
                    $this->free();
                }
                $this->clearResults(); // <----------- recursive call is your friend
            }
        }
    }
.......
}
mitchind 04-Feb-2010 08:28
After reading through original notes and example above as well as wading through the documentation, I finally got a loop to work with two stored procedures.

Using the results of the first one as a parameter for the second one. Easier to do this way than a huge modified sequence of Inner Join queries.

Hope this helps others...

<?php
// Connect to server and database
$mysqli        = new mysqli("$dbServer", "$dbUser", "$dbPass", "$dbName");

// Open First Stored Procedure using MYSQLI_STORE_RESULT to retain for looping
$resultPicks = $mysqli->query("CALL $proc ($searchDate, $maxRSI, $incRSI, $minMACD, $minVol, $minTrades, $minClose, $maxClose)", MYSQLI_STORE_RESULT);

// process one row at a time from first SP
while($picksRow = $resultPicks->fetch_array(MYSQLI_ASSOC)) {
   
// Get Parameter for next SP
   
$symbol     = $picksRow['Symbol'];

   
// Free stored results
   
clearStoredResults($mysqli);

   
// Execute second SP using value from first as a parameter (MYSQLI_USE_RESULT and free result right away)
   
$resultData    = $mysqli->query("CALL prcGetLastMACDDatesBelowZero('$symbol', $searchDate)", MYSQLI_USE_RESULT);
   
$dataRow    = $resultData->fetch_array(MYSQLI_ASSOC);

   
// Dump result from both related queries
   
echo "<p>$symbol ... Num Dates: " . $dataRow['NumDates'];

   
// Free results from second SP
   
$resultData->free();

}

// Free results from first SP
$resultPicks->free();

// close connections
$mysqli->close();

#------------------------------------------
function clearStoredResults($mysqli_link){
#------------------------------------------
   
while($mysqli_link->next_result()){
      if(
$l_result = $mysqli_link->store_result()){
             
$l_result->free();
      }
    }
}
?>
Warner 21-Jul-2009 02:45
It also seems, that executing a SET statement in multi_query() returns an extra recordset too, which one would not expect.
lau at goldenweb dot com dot au 13-Apr-2007 01:29
Beware when using stored procedures:
If you connect to the database and then call dbproc A followed by a call to db proc B and then close the connection to the db, the second procedure call will not work.

It looks like there is a bug in MYSQL or mysqli that returns an extra recordset than you would expect. It then doesn't let you call another stored procedure until you finish processing all the recordsets from the first stored procedure call.

The solution is to simply loop through the additional recordsets between calls to db procs. Here is a function that I call between db proc calls:

<?php
#--------------------------------
function ClearRecordsets($p_Result){
#--------------------------------
   
$p_Result->free();   
    while(
$this->Mysqli->next_result()){
      if(
$l_result = $this->Mysqli->store_result()){
             
$l_result->free();
      }
    }
}

?>