Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : MySQL Functions : mysql_unbuffered_query

mysql_unbuffered_query

Send an SQL query to MySQL, without fetching and buffering the result rows (PHP 4 >= 4.0.6, PHP 5, PECL mysql:1.0)
resource mysql_unbuffered_query ( string query [, resource link_identifier] )


Code Examples / Notes » mysql_unbuffered_query

david

You are absolutely required to retrieve all rows in the result set (option 'a' in the first comment). If you fail to do so, PHP will do so for you, and will emit a NOTICE warning you of the fact. From the MySQL API, "Furthermore, you must retrieve all the rows even if you determine in mid-retrieval that you've found the information you were looking for. ".
Also note that if you are using this function, you should be quick about processing the result set, or you will tie up the MySQL server (other threads will be unable to write to the tables you are reading from).
If you want to be able to 'abort' mid result-set or if you want to do lengthy processing on the results, you are misunderstanding the purpose of this function.
Also note that UPDATE queries etc return no result set, so this function is only useful for SELECT etc.


14-jun-2003 06:35

The other hand should really be, that the table remains locked until all rows have been retrieved, right?  This is a very important thing to mention, you could tie up the whole database with a lock.

chabotc

Stefan,
unbuffered query sends a query to the server, and does not first download the results before sending them to the end-user (php in this case).
So what it means is that -normaly- you could do this:
$res1 = mysql_query("select some",$db_conn);
while ($row = mysql_fetch_row($res)) {
 $res2 = mysql_query("select some other",$db_conn);
 // do some other stuff
}
With an unbuffered query you could NOT do this, the result set from $res1 would be LOST on the second query.
However, it does not mean you -have- to fetch all rows ... just that the API does not save the result set in memory for you.
However, when using different db connections, it all works ofcource ...
For more information, please refer to the mysql manual, they have a lot of docs on query & unbuffered queries (the php api is just a basic wrapper around there native api's).


shaner

Regarding bailing on a really large result, while doing an unbuffered query, there _is_ a way to do this: kill the thread and exit your processing loop.  This, of course, requires having a separate database link.  Something like below does the trick:
// a db link for queries
$lh  = mysql_connect( 'server', 'uname', 'pword' );
// and a controller link
$clh = mysql_connect( 'server', 'uname', 'pword', true );
if ( mysql_select_db ( 'big_database', $lh ) )
{
 $began  =  time();
 $tout   = 60 * 5; // five minute limit
 $qry    = "SELECT * FROM my_bigass_table";
 $rh     = mysql_unbuffered_query( $qry, $lh );
 $thread = mysql_thread_id ( $lh );
 while ( $res = mysql_fetch_row( $rh ) )
 {
   /* do what you need to do
    * ...
    * ...
    */
   if ( ( time() - $began ) > $tout )
   {
     // this is taking too long
     mysql_query( "KILL $thread", $clh );
     break;
   }
 }
}


silvanojr

Note:  The benefits of mysql_unbuffered_query() come at a cost: You cannot use mysql_num_rows() and...
but it looks like you can use SQL_CALC_ROWS on MySQL to get the total rows without the limit.


typer85

In response to "silvanojr at gmail dot com".
Your misunderstanding the point of this function. You MUST retrieve all rows in the result set BEFORE you issue another query.
Yes you can do a SQL_CALC_ROWS but that would mean you would have to query MySQL, thus either firing an error or deleting the previous query's result set as the new unbuffered result set would point to the result of the call to SQL_CALC_ROWS.
Keep that in mind folks,


andre dot steffens

If you use mysql_ping() to check the connection, the resultset from mysql_unbuffered_query() will be kill.

steve_stockman

If you are going to do a large query, but are concerned about blocking access to the table during an unbuffered query, why not go through a temporary table? (Of course, this is predicated on the current user having permission to create tables.)
$dbQuery = "SELECT something ...";
if (mysql_query ("CREATE TEMPORARY TABLE MyQuery $dbQuery")) {
   $numRows = mysql_affected_rows();
   if ($numRows == 0) {
       /* handle empty selection */
   } else {
       $result = mysql_unbuffered_query ('SELECT * FROM MyQuery');
       /* handle result */
   }
   mysql_query ('DROP TABLE MyQuery');
}


post

If using optimized MyISAM tables I guess there is a big advantage with this function as it is possible to do selects and inserts on the same time as long as no rows in the table gets updated.

frappyjohn

Don't let the two hands confuse you, these are both advantages (they should really be on the same hand):
On the one hand, this saves a considerable amount of memory with SQL queries that produce large result sets.
On the other hand, you can start working on the result set immediately ...


Change Language


Follow Navioo On Twitter
mysql_affected_rows
mysql_change_user
mysql_client_encoding
mysql_close
mysql_connect
mysql_create_db
mysql_data_seek
mysql_db_name
mysql_db_query
mysql_drop_db
mysql_errno
mysql_error
mysql_escape_string
mysql_fetch_array
mysql_fetch_assoc
mysql_fetch_field
mysql_fetch_lengths
mysql_fetch_object
mysql_fetch_row
mysql_field_flags
mysql_field_len
mysql_field_name
mysql_field_seek
mysql_field_table
mysql_field_type
mysql_free_result
mysql_get_client_info
mysql_get_host_info
mysql_get_proto_info
mysql_get_server_info
mysql_info
mysql_insert_id
mysql_list_dbs
mysql_list_fields
mysql_list_processes
mysql_list_tables
mysql_num_fields
mysql_num_rows
mysql_pconnect
mysql_ping
mysql_query
mysql_real_escape_string
mysql_result
mysql_select_db
mysql_set_charset
mysql_stat
mysql_tablename
mysql_thread_id
mysql_unbuffered_query
eXTReMe Tracker