I'm trying to get a number of columns from a PDO resultset into seperate arrays, so resulting as such:
<?php
$query = 'SELECT col1,col2 FROM tbl_imaginary';
...
$col1 = array(col1_row1, col1_row2,...);
$col2 = array(col2_row1, col2_row2,...);
?>
I know I could loop through the resultset with fetch, but it seems more efficient to use fetchAll(PDO:FETCH_COLUMN). However, once you do this, you can't perform it again unless you perform execute() on the statement handle again. I get why, you can't empty the cookie jar and then do the same again unless you fill it up again - kind of thing. So I thought I would copy the statement handle object and fetch columns of it as such:
<?php
$sh->execute();
for ($i=0; $i<$sh->columnCount(); $i++)
{
$tmp_sh = $sh;
$output[$i] = $tmp_sh->fetchAll(PDO::FETCH_COLUMN);
}
?>
However, this, just like doing fetchAll() on the original statement handle itself, outputs only the first column and not the second.
If anyone would be so kind to explain this behaviour to me and / or suggest a solution I would be most grateful.
Thank you very much in advance for your time.
Edit: So basically I want to get 2 (or more) columns from one resultset as seperate arrays, just like you would if you would perform 2 (or more) individual queries on 1 single column. The above is mostly an explanation of how I've tried to do this so far.
Why do you need two separate arrays?
$statement = $db->prepare('SELECT col1, col2 FROM tbl_imaginary');
$statement->execute();
foreach($sth->fetchAll() as $row) {
echo $row['col1'], $row['col2'];
}
Related
I have an array from which I would like to populate table records from, unfortunately it will only populate the 1st record of the array. I anticipate I have my increments declared incorrectly, but cannot find a combination that will work. In addition I would like '$mtcelogID = $siteNAME.'.'.$Maindate.'.'.$i;' to have the last part of the ID to increment
$mtcelogARRAY = $objPHPExcel->setActiveSheetIndex(2)->rangeToArray('A8:A18');
$num_mtcelog = count($mtcelogARRAY); // Here get total count of row in that Excel sheet
for( $i=0; $i<=$num_mtcelog; $i++ ){
$sql_mtcelog = "INSERT INTO `maintenance_log`(`mtcelogID`,`mtcelogTYPE`,`MaintenanceID`) VALUES (?,?,?)";
$query_mtcelogARRAY = mysqli_prepare($link, $sql_mtcelog);
$mtcelogID = $siteNAME.'.'.$Maindate.'.'.$i;
mysqli_stmt_bind_param($query_mtcelogARRAY,"sss", $mtcelogID, $mtcelogARRAY[$i][0], $MaintenanceID);
mysqli_stmt_execute($query_mtcelogARRAY);
mysqli_stmt_close($query_mtcelogARRAY);
}
The above code returns this in my PHP table:
And my array looks like this:
Thanks in advance
I know you're using mysqli, but I'm going to leave this PDO answer here. If this code is a small maintenance script, there shouldn't be any trouble dumping mysqli. Notice no binding is necessary, you just pass the values as an array to PDOStatement::execute(). No worrying about how many s and i you have. Also, foreach is a much more flexible and less verbose construct than for.
$pdo = new PDO("mysql:host=localhost;dbname=mydatabase", $username, $password);
$mtcelogARRAY = $objPHPExcel->setActiveSheetIndex(2)->rangeToArray('A8:A18');
$sql_mtcelog = "INSERT INTO `maintenance_log`(`mtcelogID`,`mtcelogTYPE`,`MaintenanceID`) VALUES (?,?,?)";
$stmt = $pdo->prepare($sql_mtcelog);
foreach ($mtcelogARRAY as $i=>$arr) {
$params = ["$siteNAME.$Maindate.$i", $arr[0], $MaintenanceID];
$stmt->execute($params);
}
The important thing is to prepare your statement outside the loop. One of the main goals of prepared statements is to reduce overhead; by preparing the statement repeatedly you are increasing overhead.
Okay, so I realize that when do:
//connection code;
//query code;
//$result= mysqli_query();
$row= mysqli_fetch_array($result);
you create an associative array where the column names from your table are the keys for the data in the respective row.
Then you can use:
while ($row= mysqli_fetch_array($result))
{
//code to echo out table data.
}
My question is how does the while loop go to the next row after each iteration? I thought that was what foreach loops were for?
From http://www.php.net/manual/en/function.mysql-fetch-array.php
array mysql_fetch_array ( resource $result [, int $result_type = MYSQL_BOTH ] )
Returns an array that corresponds to the fetched row and moves the internal data pointer ahead.
Many functions that return a result set do so by returning an array that you can do a foreach() on like you are used to. This is not always the case however, especially with database functions. mysqli_fetch_array fetches just a single row, or returns boolean false if there are no more remaining. This is how the loop works: the expression evaluates to true as long as there is a row to process.
The reason for this construction is mainly efficiency. Fetching database rows can be a performance critical operation, and there are cases where not all rows are needed. In these situations this approach will give more flexibility. Fetching rows one-by-one is also more memory-friendly since not all result data will have to be loaded into memory at once.
Mysqli actually has a function that does fetch the entire result set in an array: mysqli_fetch_all. You will be able to foreach() over that.
mysql_fetch_array simply fetches the next row of the result set from your mysql query and returns the row as an array or false if there are no more rows to fetch.
The while loops continually pulls the results, one at a time from the result set and continues until mysql_fetch_array is false.
A foreach loop loops through each value of an array. As mysql_fetch_array only pulls one result and therefore the value of count($row) would be 1 every time.
Each time the while loop runs, it executes the function mysql_fetch_array and gets the next result. It does that until there aren't more results to show.
mysql_fetch_array returns an array of strings that corresponds to the fetched row, or FALSE if there are no more rows. If row exists then get data.
I hope this has answered you q. Its hard to understand what you mean
This part fetches one row at a time
$row = mysqli_fetch_array($result);
Putting it into a while loop makes it fetch one row at a time, until it does not fetch a row because there are no more to be fetched.
The alternative would be to fetch all the rows, then loop through them with a foreach
$rows = mysql_fetch_all($result);
foreach($rows as $row){
// do something with row
}
For this to work, you have to make yourself a mysql_fetch_all function, which of course has the original while loop in it...
function mysql_fetch_all($result)
{
$all = array();
while($thing = mysql_fetch_assoc($result)) {
$all[] = $thing;
}
return $all;
}
This works due to the SQL connector storing the current state of the query (i.e. the next result row to return) inside the result.
If you want a similar example, it works like reading from a file, where you're able to use similar constructs:
while ($line = fgets($fp, 1000)) {
// ...
}
Behind the scenes (and depending on the language, interpreter, compiler, etc.) for and while essentially result in the same code. The difference is, depending on what your code should do, one approach could be more readable than the other.
Take the following two loops as an example. Both do exactly the same.
for ($i = 0; $i < 10; $i++) {
// ...
}
$i = 0;
while ($i < 10) {
// ...
$i++;
}
I have a table with 4 columns and 23 rows. I need all 92 values in the the table as PHP variables (whether that be one array, 4 arrays, 92 individual variables, or whatever).
The rows are:
ID
Category
Summary
Text
I need to build a series of select boxes where the items are grouped by the category, the options available are the summaries, and the resulting text is passed on for processing.
I've been searching, but all the examples I can find are about printing the table out, and I need to continue working with the variables.
I really appreciate any help!
Billy
Just a SELECT * FROM table_name will select all the columns and rows.
$query = "SELECT * FROM table_name";
$result = mysql_query($query);
$num = mysql_num_rows($results);
if ($num > 0) {
while ($row = mysql_fetch_assoc($result)) {
// You have $row['ID'], $row['Category'], $row['Summary'], $row['Text']
}
}
OK, I found my answer with better search terms. I'm still new here, so let me know if this is not a fair way to handle the situation. I upvoted #Indranil since he or she spent so much time trying to help me.
Anyway...
$content = array();
while($row = mysql_fetch_assoc($result)) {
$content[$row['id']] = $row;
}
Puts my whole entire table into one huge, multidimensional array so that I can use it throughout my code. And it even names the first level of the array by the ID (which is the unique identifier).
Thank you to those that tried to help me!
Billy
$pdo = new PDO(
'mysql:host=hostname;dbname=database;charset=utf-8',
'username',
'password'
);
$pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$stmt = $pdo->query('SELECT ID, Category, Summary, Text FROM Table');
if ( $stmt !== false )
{
$data = $stmt->fetchAll( PDO::FETCH_ASSOC );
}
In the case if the SQL query has no conditions, use query() , otherwise, you should be using prepare() ans bind the parameters.
Oh .. and please stop using the ancient mysql_* functions, they are in the process of being deprecated and no new code should written with them.
I'm using a concrete implementation of Zend_Db_Table_Abstract:
class DB_TestClass extends Zend_Db_Table_Abstract {
protected $_name = "test.TestData";
}
If I want select all rows in the table, I seem to have one option:
$t = new DB_TestClass;
$rowset = $t->fetchAll();
This returns an instance of Zend_Db_Table_Rowset which has an iterable interface you can loop though and access each row entry as a rowClass instance:
foreach($rowset as $row) {
var_dump($row);
}
HOWEVER, the rowset has loaded every row from the database into memory(!) On small tables this is OK, but on large tables - thousands of rows, for example - it quickly exhausts the memory available to PHP and the script dies.
How can I, using Zend_Db, iterate through the result set retrieving one row from a statement handle at a time, ala mysql_fetch_assoc()? This would allow efficient access to any number of rows (thousands, millions) without using excessive memory.
Thanks in advance for any suggestions.
Then fetchAll () is not capable of what you want.
You need to use Zend_Db_Select to get all the records and then do what you've intended through the loop
$select = new Zend_Db_Select ($this->getFrontController()->getParam('bootstrap')->getResource ('Db'));
$statement = $select->from ('verses')->query ();
$statement->execute ();
while ($row = $statement->fetch ())
{
// try something like that
$db_row = new Zend_Db_Table_Row (array ('table' => $table, 'data' => $row));
$db_row->text = $db_row->text . '_';
$db_row->save ();
}
Can you please specify the purpose for fetching all the rows together? Cause if you want to do some kind of processing on all the rows in the table then you any which ways have to get all the rows in to the memory. On the other hand if you want to do something like pagination, you can always use zend_pagination object which will just fetch the limited no. of rows at one time. Or better still you can set the offset and no. of rows to be fetched in the fetchAll function itself.
I have two dynamic tables (tabx and taby) which are created and maintained through a php interface where columns can be added, deleted, renamed etc.
I want to read all columns simulataneously from the two tables like so;-
select * from tabx,taby where ... ;
I want to be able to tell from the result of the query whether each column came from either tabx or taby - is there a way to force mysql to return fully qualified column names e.g. tabx.col1, tabx.col2, taby.coln etc?
In PHP, you can get the field information from the result, like so (stolen from a project I wrote long ago):
/*
Similar to mysql_fetch_assoc(), this function returns an associative array
given a mysql resource, but prepends the table name (or table alias, if
used in the query) to the column name, effectively namespacing the column
names and allowing SELECTS for column names that would otherwise have collided
when building a row's associative array.
*/
function mysql_fetch_assoc_with_table_names($resource) {
// get a numerically indexed row, which includes all fields, even if their names collide
$row = mysql_fetch_row($resource);
if( ! $row)
return $row;
$result = array();
$size = count($row);
for($i = 0; $i < $size; $i++) {
// now fetch the field information
$info = mysql_fetch_field($resource, $i);
$table = $info->table;
$name = $info->name;
// and make an associative array, where the key is $table.$name
$result["$table.$name"] = $row[$i]; // e.g. $result["user.name"] = "Joe Schmoe";
}
return $result;
}
Then you can use it like this:
$resource = mysql_query("SELECT * FROM user JOIN question USING (user_id)");
while($row = mysql_fetch_assoc_with_table_names($resource)) {
echo $row['question.title'] . ' Asked by ' . $row['user.name'] . "\n";
}
So to answer your question directly, the table name data is always sent by MySQL -- It's up to the client to tell you where each column came from. If you really want MySQL to return each column name unambiguously, you will need to modify your queries to do the aliasing explicitly, like #Shabbyrobe suggested.
select * from tabx tx, taby ty where ... ;
Does:
SELECT tabx.*, taby.* FROM tabx, taby WHERE ...
work?
I'm left wondering what you are trying to accomplish. First of all, adding and removing columns from a table is a strange practice; it implies that the schema of your data is changing at run-time.
Furthermore, to query from the two tables at the same time, there should be some kind of relationship between them. Rows in one table should be correlated in some way with rows of the other table. If this is not the case, you're better off doing two separate SELECT queries.
The answer to your question has already been given: SELECT tablename.* to retrieve all the columns from the given table. This may or may not work correctly if there are columns with the same name in both tables; you should look that up in the documentation.
Could you give us more information on the problem you're trying to solve? I think there's a good chance you're going about this the wrong way.
Leaving aside any questions about why you might want to do this, and why you would want to do a cross join here at all, here's the best way I can come up with off the top of my head.
You could try doing an EXPLAIN on each table and build the select statement programatically from the result. Here's a poor example of a script which will give you a dynamically generated field list with aliases. This will increase the number of queries you perform though as each table in the dynamically generated query will cause an EXPLAIN query to be fired (although this could be mitigated with caching fairly easily).
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
function aliasFields($pdo, $table, $delim='__') {
$fields = array();
// gotta sanitise the table name - can't do it with prepared statement
$table = preg_replace('/[^A-z0-9_]/', "", $table);
foreach ($pdo->query("EXPLAIN `".$table."`") as $row) {
$fields[] = $table.'.'.$row['Field'].' as '.$table.$delim.$row['Field'];
}
return $fields;
}
$fieldAliases = array_merge(aliasFields($pdo, 'artist'), aliasFields($pdo, 'event'));
$query = 'SELECT '.implode(', ', $fieldAliases).' FROM artist, event';
echo $query;
The result is a query that looks like this, with the table and column name separated by two underscores (or whatever delimeter you like, see the third parameter to aliasFields()):
// ABOVE PROGRAM'S OUTPUT (assuming database exists)
SELECT artist__artist_id, artist__event_id, artist__artist_name, event__event_id, event__event_name FROM artist, event
From there, when you iterate over the results, you can just do an explode on each field name with the same delimeter to get the table name and field name.
John Douthat's answer is much better than the above. It would only be useful if the field metadata was not returned by the database, as PDO threatens may be the case with some drivers.
Here is a simple snippet for how to do what John suggetsted using PDO instead of mysql_*():
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$query = 'SELECT artist.*, eventartist.* FROM artist, eventartist LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch()) {
foreach ($row as $key=>$value) {
if (is_int($key)) {
$meta = $stmt->getColumnMeta($key);
echo $meta['table'].".".$meta['name']."<br />";
}
}
}