Description
Fetching Individual Rows From Query Results
The MDB2_Result_Common object provides two
methods for fetching data from rows of a result set:
fetchOne(),
fetchRow(),
fetchCol() and
fetchAll().
fetchRow() and fetchOne() read an
entire row or a single field from a column respectively. The result pointer
gets moved to the next row each time these methods are called. NULL is
returned when the end of the result set is reached.
fetchAll() and fetchCol() read all
rows in the result set and therefore move the result pointer to the end.
While fetchAll() reads the entire row data,
fetchCol() only reads a single column.
MDB2_Error is returned if an error is encountered.
Fetching a result set
<?php // Create a valid MDB2 object named $mdb2 // at the beginning of your program... require_once 'MDB2.php';
$mdb2 =& MDB2::connect('pgsql://usr:pw@localhost/dbnam'); if (PEAR::isError($mdb2)) { die($mdb2->getMessage()); }
// Proceed with getting some data... $res =& $mdb2->query('SELECT * FROM mytable');
// Get each row of data on each iteration until // there are no more rows while (($row = $res->fetchRow())) { // Assuming MDB2's default fetchmode is MDB2_FETCHMODE_ORDERED echo $row[0] . "\n"; }
// while (($one = $res->fetchOne())) { // echo $one . "\n"; // }
?>
|
Formats of Fetched Rows
The data from the row of a query result can be
placed into one of three constructs:
an ordered array (with column numbers as keys),
an associative array (with column names as keys) or
an object (with column names as properties).
MDB2_FETCHMODE_ORDERED (default)
Array ( [0] => 28 [1] => hi )
|
MDB2_FETCHMODE_ASSOC
Array ( [a] => 28 [b] => hi )
|
MDB2_FETCHMODE_OBJECT
stdClass Object ( [a] => 28 [b] => hi )
|
NOTE: When a query contains the same column name more
than once (such as when joining tables which have
duplicate column names) and the fetch mode is
MDB2_FETCHMODE_ASSOC or
MDB2_FETCHMODE_OBJECT,
the data from the last column with a given name will
be the one returned. There are two immediate options
to work around this issue:
-
Use aliases in your query, for example
People.Name AS PersonName
-
Change the fetch mode to MDB2_FETCHMODE_ORDERED
TIP: If you are running into this issue, it likely
indicates poor planning of the database schema. Either
data is needlessly being duplicated or the same names are
being used for different kinds of data.
How to Set Formats
You can set the fetch mode each time you call a
fetch method and/or you can set the default fetch
mode for the whole MDB2 instance by using the
setFetchMode() method.
Determining fetch mode per call
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM users');
while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) { echo $row['id'] . "\n"; } ?>
|
Changing default fetch mode
<?php // Once you have a valid MDB2 object named $mdb2... $mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
$res =& $mdb2->query('SELECT * FROM users');
while ($row = $res->fetchRow()) { echo $row['id'] . "\n"; } ?>
|
Fetch Rows by Number
The PEAR MDB2 fetch system also supports an extra parameter
to the fetch statement. So you can fetch rows from a result
by number. This is especially helpful if you only want to show
sets of an entire result (for example in building paginated
HTML lists), fetch rows in an special order, etc.
Fetching by number
<?php // Once you have a valid MDB2_Result object named $res...
// the row to start fetching $from = 50;
// how many results per page $resPage = 10;
// the last row to fetch for this page $to = $from + $resPage;
foreach (range($from, $to) as $rowNum) { if (!($row = $res->fetchRow(MDB2_FETCHMODE_ORDERED, $rowNum))) { break; } echo $row[0] . "\n"; } ?>
|
Getting Entire Result Sets
The MDB2_Result_Common object provides several
methods to read entire results sets:
fetchCol() and
fetchAll().
Freeing Result Sets
Once you finish using a result set, if your script
continues for a while, it's a good idea to save
memory by freeing the result set via
Use
free().
Freeing
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT name, address FROM clients'); while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) { echo $row['name'] . ', ' . $row['address'] . "\n"; } $res->free(); ?>
|
Getting the native result resource
If whatever data you need to read from a result set is not yet implemented
in MDB2 you can get the native result resource using the
getResource() method and then call the
underlying PHP extension directly (though this would of course require that
it is now up to you to make this sufficiently portable).
Native result resource
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT name, address FROM clients'); $native_result = $res->getResource(); ?>
|
Getting More Information From Query Results
With MDB2 there are four ways to retrieve useful
information about the query result sets themselves:
numRows() tells how many
rows are in a SELECT query result
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM phptest'); if ($mdb2->getOption('result_buffering')) { echo $res->numRows(); } else { echo 'cannot get number of rows in the result set when "result_buffering" is disabled'; } ?>
|
numCols() tells how many
columns are in a SELECT query result
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM phptest'); echo $res->numCols(); ?>
|
rowCount() tells which row number
the internal result row pointer currently points to
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM phptest'); $res->fetchRow(); // returns 2 if the result set contains at least 2 rows echo $res->rowCount();
?>
|
getColumnNames() returns an associative
array with the names of the column of the result set as keys and the
position inside the result set as the values
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM phptest'); print_r($res->getColumnNames());
?>
|
seek() allows to seek to a specific row inside
a result set. Note that seeking to previously read rows is only possible
if the 'result_buffering' option is left enabled, otherwise only forward
seeking is supported.
<?php // Once you have a valid MDB2 object named $mdb2... $res =& $mdb2->query('SELECT * FROM phptest'); // Seek to the 10th row in the result set $res->seek(10));
?>
|
nextResult() allows iterate over multiple
results returned by a multi query.
<?php // Once you have a valid MDB2 object named $mdb2... $multi_query = $this->db->setOption('multi_query', true); // check if multi_query can be enabled if (!PEAR::isError($multi_query)) { $res =& $mdb2->query('SELECT * FROM phptest; SELECT * FROM phptest2;'); $data1 = $res->fetchAll(); // move result pointer to the next result $res->nextResult(); $data2 = $res->fetchAll(); } else { echo 'multi_query option is not supported'; }
?>
|
bindColumn() allows to bind a reference to
a user variable to a specific field inside the result set. This means that
when fetching the next row, this variable is automatically updated.
<?php // Once you have a valid MDB2 object named $mdb2... $name = $address = null; $res =& $mdb2->query('SELECT id, name, address FROM clients', array('id' => 'integer')); $res->bindColumn('id', $id); // provide a type for the column not included in the query() call $res->bindColumn('name', $name, 'text'); // but specifying a type is as always optional in MDB2 $res->bindColumn('address', $address); while ($res->fetchRow()) { echo "The address of '$name' (user id '$id') is '$address'\n"; } ?>
|
Querying and fetching in one call
All of the fetch methods are also available in a variant that executes a
query directly:
queryOne(),
queryRow(),
queryCol() and
queryAll().
<?php // Once you have a valid MDB2 object named $mdb2... $data = $mdb2->queryAll('SELECT * FROM phptest'); print_r($data);
?>
|
Users that prefer to use prepared statements can make use of the
following methods from the
Extended module:
getOne(),
getRow(),
getCol(),
getAll() and
getAssoc().
<?php // Once you have a valid MDB2 object named $mdb2... $mdb2->loadModule('Extended'); $query = 'SELECT * FROM phptest WHERE id = ?'; $data = $mdb2->extended->getRow($query, null, array(1), array('integer')); print_r($data);
?>
|
Data types
MDB2 supports a number of data types across all drivers. These can be set
for result sets at query or prepare time or using the
setResultTypes() method.
You can find an overview of the supported data types and their format
here.
Fetching LOBs
To retrieve a Large Object (BLOB or CLOB), you can use streams, as you were reading a file
Fetching LOBs with streams.
<?php $result =& $mdb2->query('SELECT document, picture FROM files WHERE id = 1', array('clob', 'blob')); if (PEAR::isError($result) || !$result->valid()) { //uh-oh } $row = $result->fetchRow();
//fetch the Character LOB into the $clob_value variable $clob = $row[0]; if (!PEAR::isError($clob) && is_resource($clob)) { $clob_value = ''; //use streams while (!feof($clob)) { $clob_value .= fread($clob, 8192); } $mdb2->datatype->destroyLOB($clob); }
//fetch the Binary LOB into the $blob_value variable $blob = $row[1]; if (!PEAR::isError($blob) && is_resource($blob)) { $blob_value = ''; while (!feof($blob)) { $blob_value.= fread($blob, 8192); } $mdb2->datatype->destroyLOB($blob); }
//free the result $result->free(); ?>
|
Checking for Errors
Don't forget to use
isError() to check
if your actions return a MDB2_Error object.