53

How can I get all the column names from a table using PDO?

id         name        age
1          Alan        35      
2          Alex        52
3          Amy         15

The info that I want to get are,

id         name        age

EDIT:

Here is my attempt,

$db = $connection->get_connection();
$select = $db->query('SELECT * FROM contacts');

$total_column = $select->columnCount();
var_dump($total_column);

for ($counter = 0; $counter < $total_column; $counter ++) {
    $meta = $select->getColumnMeta($counter);
    $column[] = $meta['name'];
}
print_r($column);

Then I get,

Array
(
    [0] => id
    [1] => name
    [2] => age
    ...

)
George
  • 4,147
  • 24
  • 33
Run
  • 54,938
  • 169
  • 450
  • 748
  • 6
    Do you want the column names in *a table*, or the column names *in the record set from a query*? These are two different things done in two different ways. Phil's answer does the former, JapanPro's answer does the latter! – Charles Mar 25 '11 at 03:37
  • @charles: I think I only want to get the column names in a table. I don't quite understand what u mean by __column names in the record set from a query__. but see my answer in my edit above. thanks. – Run Mar 25 '11 at 04:09
  • @lauthiamkok: You're doing that in your updated post -- you're making a query, which returns a set of records, then you're grabbing the column names *for that specific set*. It just happens that the column names in your result set are identical to those in your table. Remember, SQL columns can be aliased. – Charles Mar 25 '11 at 04:13
  • 1
    @lauthiamkok, if you were trying to get the column names from a table, then @JapanPro's answer below is the best way to do that -- using the `information_schema` method. What you are doing *does the job* but isn't the "right" way. – Charles Mar 25 '11 at 04:26
  • 2
    when you have an empty table your method fails, because there's no records to fetch the columns from. – SparK Dec 15 '11 at 21:32

14 Answers14

94

I solve the problem the following way (MySQL only)

$table_fields = $dbh->query("DESCRIBE tablename")->fetchAll(PDO::FETCH_COLUMN);
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Jesper Grann Laursen
  • 2,357
  • 1
  • 20
  • 21
  • 18
    This is only supported by MySQL. – Tom Macdonald Mar 23 '12 at 16:44
  • 10
    why not `$q = $dbh->query("DESCRIBE tablename"); $table_fields = $q->fetchAll(PDO::FETCH_COLUMN);`? – Francisco Presencia Jan 10 '13 at 17:34
  • 3
    Reader, for a generic solution, see @Will answer. – Peter Krauss Jul 03 '13 at 11:22
  • IMHO, while this answer may be useful to many, it doesn't match the need expressed in the question, i.e. "Is there a way to retrieve the column name from the rowset array while I'm iterating data?" The user wants to see the key in the array while iterating values. The key($array) function may help. – ManuelJE Dec 13 '18 at 15:08
44

This will work for MySQL, Postgres, and probably any other PDO driver that uses the LIMIT clause.

Notice LIMIT 0 is added for improved performance:

$rs = $db->query('SELECT * FROM my_table LIMIT 0');
for ($i = 0; $i < $rs->columnCount(); $i++) {
    $col = $rs->getColumnMeta($i);
    $columns[] = $col['name'];
}
print_r($columns);
Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
Will
  • 948
  • 8
  • 11
  • 1
    Thanks Will! Hello reader, that is the generic PDO solution! The Lauer solution only supported by MySQL -- and PDOStatement::getColumnMeta() is complex, is not supported for all PDO drivers, and is listed as experimental. PS: the query runs also with empty tables. – Peter Krauss Jul 03 '13 at 11:14
  • 1
    Perhaps simplify with something like `$columns = array_keys($rs->fetchAll(PDO::FETCH_ASSOC));`... I not try. – Peter Krauss Jul 03 '13 at 11:33
  • @PeterKrauss, I tried your second comment, there are no results (no columns even) if the LIMIT is 0. – David d C e Freitas Apr 16 '14 at 23:34
  • ... hum... And (for check where the bug) changing SQL to `LIMIT 1` (in a not-empty table) it works? – Peter Krauss Apr 16 '14 at 23:56
  • 1
    @PeterKrauss, yeah, it needs at least one result. – David d C e Freitas Apr 22 '14 at 03:42
  • 3
    @DaviddCeFreitas, sorry the method [getColumnMeta](http://www.php.net/manual/en/pdostatement.getcolumnmeta.php) have a 6+ years old "is EXPERIMENTAL" alert...The only way is using a non-empty table. You can use something like `SELECT * FROM my_table WHERE id=0` and populate all tables with a no-data row. – Peter Krauss Apr 22 '14 at 08:45
  • 1
    LIMIT 0 is a MySQL / PGSQL specific syntax. *How* is this generic? How to make it so? – Ber May 08 '16 at 02:52
  • Postgres PDO getColumnMet will not work for this SQL: select 'abc', 123 -- any idea to get column name? the output will be ?column? If MySQL, it will show 'abc', 123 as column names – SIDU Jan 10 '17 at 02:51
  • @ber A universal answer would be to replace your SELECT: 'SELECT * FROM my_table WHERE 3 < 2'. I believe (but have not done exhaustive testing) that the performance of that statement (at least for MYSQL, DB2, Oracle) will rival LIMIT 0. (You could use any other "always false" test.) – Dennis Jun 24 '22 at 23:43
22

My 2 cents:

$result = $db->query('select * from table limit 1');
$fields = array_keys($result->fetch(PDO::FETCH_ASSOC));

And you will get the column names as an array in the var $fields.

ragnar
  • 1,252
  • 11
  • 18
  • 1
    This produces a Warning if the table is empty! ===> "Warning: array_keys() expects parameter 1 to be array, bool given in..." – Oliver M Grech Apr 10 '21 at 22:13
15

A simple PHP function

function getColumnNames($pdo, $table) {
    $sql = "SELECT column_name FROM information_schema.columns WHERE table_name = ?";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$table]);
    return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Pramendra Gupta
  • 14,667
  • 4
  • 33
  • 34
  • add also `schema_name` to `where` – zerkms Mar 25 '11 at 03:38
  • 4
    +1 for `information_schema` instead of something DB-specific. – Charles Mar 25 '11 at 03:40
  • @Charles Isn't `information_schema` MySQL specific? This question isn't tagged `MySQL` so it could be anything. Mind you, the method in my answer probably doesn't work on every DB either ;) – Phil Mar 25 '11 at 03:43
  • 3
    @Phil, [`information_schema`](http://en.wikipedia.org/wiki/Information_schema) is part of the ANSI standard. It's been implemented in MySQL, PostgreSQL and MSSQL. Unless the OP is using Oracle or SQLite, it should work fine for him (assuming this answer was what he wanted). – Charles Mar 25 '11 at 03:45
  • @Charles Thanks, learned something. Hadn't seen it in MSSQL and the only other DB I've worked with is Oracle – Phil Mar 25 '11 at 03:47
  • Just checked this solution, and it appears to show missleading results when the user has access to two databases, which both have a table `myTable`. The result is a combined list of columns in __both__ the tables, instead of the list of of columns in the particular table in the current database. – Paweł Stawarz Sep 15 '14 at 19:23
  • 1
    @PawełStawarz there is a TABLE_SCHEMA column that indicates what schema the table and column belong to. However, the downsides to using information_schema is that it is possible not all users/accounts will have access to this system table. This is also slower than getColumnMeta(). – RyanNerd Feb 02 '16 at 17:46
  • @PawełStawarz - did you find a solution to solving the 2 tables in 2 db's issue? – James Wilson Nov 15 '17 at 13:26
  • @JamesWilson No, I just used ragnars solution instead: https://stackoverflow.com/a/19684307/2180870 – Paweł Stawarz Nov 15 '17 at 17:46
2

Here is the function I use. Created based on @Lauer answer above and some other resources:

//Get Columns
function getColumns($tablenames) {
global $hostname , $dbnames, $username, $password;
try {
$condb = new PDO("mysql:host=$hostname;dbname=$dbnames", $username, $password);

//debug connection
$condb->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$condb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// get column names
$query = $condb->prepare("DESCRIBE $tablenames");
$query->execute();
$table_names = $query->fetchAll(PDO::FETCH_COLUMN);
return $table_names;

//Close connection
$condb = null;

} catch(PDOExcepetion $e) {
echo $e->getMessage();
}
}

Usage Example:

$columns = getColumns('name_of_table'); // OR getColumns($name_of_table); if you are using variable.

foreach($columns as $col) {
echo $col . '<br/>';
}
Ari
  • 4,643
  • 5
  • 36
  • 52
2

This is an old question but here's my input

function getColumns($dbhandle, $tableName) {
    $columnsquery = $dbhandle->query("PRAGMA table_info($tableName)");
    $columns = array();
    foreach ($columnsquery as $k) {
        $columns[] = $k['name'];
    }
    return $columns;
}

just put your variable for your pdo object and the tablename. Works for me

Dave
  • 21
  • 1
2

This approach works for me in SQLite and MySQL. It may work with others, please let me know your experience.

  • Works if rows are present
  • Works if no rows are present (test with DELETE FROM table)

Code:

$calendarDatabase = new \PDO('sqlite:calendar-of-tasks.db');    
$statement = $calendarDatabase->query('SELECT *, COUNT(*) FROM data LIMIT 1');
$columns = array_keys($statement->fetch(PDO::FETCH_ASSOC));
array_pop($columns);
var_dump($columns);

I make no guarantees that this is valid SQL per ANSI or other, but it works for me.

William Entriken
  • 37,208
  • 23
  • 149
  • 195
1

PDOStatement::getColumnMeta()

As Charle's mentioned, this is a statement method, meaning it fetches the column data from a prepared statement (query).

Phil
  • 157,677
  • 23
  • 242
  • 245
1

I needed this and made a simple function to get this done.

function getQueryColumns($q, $pdo){
    $stmt = $pdo->prepare($q);
    $stmt->execute();
    $colCount = $stmt->columnCount();
    $return = array();
    for($i=0;$i<$colCount;$i++){
        $meta = $stmt->getColumnMeta($i);
        $return[] = $meta['name'];
    }
    return $return;
}

Enjoy :)

Oliver M Grech
  • 3,071
  • 1
  • 21
  • 36
0

A very useful solution here for SQLite3. Because the OP does not indicate MySQL specifically and there was a failed attempt to use some solutions on SQLite.

    $table_name = 'content_containers';
    $container_result = $connect->query("PRAGMA table_info(" . $table_name . ")");
    $container_result->setFetchMode(PDO::FETCH_ASSOC);


    foreach ($container_result as $conkey => $convalue)
    {

        $elements[$convalue['name']] = $convalue['name'];

    }

This returns an array. Since this is a direct information dump you'll need to iterate over and filter the results to get something like this:

Array
(
    [ccid] => ccid
    [administration_title] => administration_title
    [content_type_id] => content_type_id
    [author_id] => author_id
    [date_created] => date_created
    [language_id] => language_id
    [publish_date] => publish_date
    [status] => status
    [relationship_ccid] => relationship_ccid
    [url_alias] => url_alias
)

This is particularly nice to have when the table is empty.

Carl McDade
  • 634
  • 9
  • 14
0

My contribution ONLY for SQLite:

/**
 * Returns an array of column names for a given table.
 * Arg. $dsn should be replaced by $this->dsn in a class definition.
 *
 * @param string $dsn Database connection string, 
 * e.g.'sqlite:/home/user3/db/mydb.sq3'
 * @param string $table The name of the table
 * 
 * @return string[] An array of table names
 */
public function getTableColumns($dsn, $table) {
   $dbh = new \PDO($dsn);
   return $dbh->query('PRAGMA table_info(`'.$table.'`)')->fetchAll(\PDO::FETCH_COLUMN, 1);
}
centurian
  • 1,168
  • 13
  • 25
-1

Just Put your Database name,username,password (Where i marked ?) and table name.& Yuuppiii!.... you get all data from your main database (with column name)

<?php 

function qry($q){

    global $qry;
    try {   
    $host = "?";
    $dbname = "?";
    $username = "?";
    $password = "?";
    $dbcon = new PDO("mysql:host=$host; 
    dbname=$dbname","$username","$password");
}
catch (Exception $e) {

    echo "ERROR ".$e->getMEssage();

}

    $qry = $dbcon->query($q);
    $qry->setFetchMode(PDO:: FETCH_OBJ);

    return $qry;

}


echo "<table>";

/*Get Colums Names in table row */
$columns = array();

$qry1= qry("SHOW COLUMNS FROM Your_table_name");

while (@$column = $qry1->fetch()->Field) {
    echo "<td>".$column."</td>";
    $columns[] = $column;

}

echo "<tr>";

/* Fetch all data into a html table * /

$qry2 = qry("SELECT * FROM Your_table_name");

while ( $details = $qry2->fetch()) {

    echo "<tr>";
    foreach ($columns as $c_name) {
    echo "<td>".$details->$c_name."</td>";

}

}

echo "</table>";

?>
dipenparmar12
  • 3,042
  • 1
  • 29
  • 39
-1
$q = $dbh->prepare("DESCRIBE tablename");
$q->execute();
$table_fields = $q->fetchAll(PDO::FETCH_COLUMN);

must be

$q = $dbh->prepare("DESCRIBE database.table");
$q->execute();
$table_fields = $q->fetchAll(PDO::FETCH_COLUMN);
-7

There is no need to do a secondary query. Just use the built in oci_field_name() function:

Here is an example:

oci_execute($stid);                  //This executes

    echo "<table border='1'>\n";
    $ncols = oci_num_fields($stid);
    echo "<tr>";
    for ($i = 1; $i <= $ncols; $i++) {
            $column_name  = oci_field_name($stid, $i);
            echo "<td>$column_name</td>";
    }
    echo "</tr>";


    while ($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
            echo "<tr>\n";
            foreach ($row as $item) {
                    echo "    <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
            }
            echo "</tr>\n";
    }
    echo "</table>\n";
TecBrat
  • 3,643
  • 3
  • 28
  • 45
Ben
  • 491
  • 4
  • 6
  • 7
    He's using PDO, not OCI. Also, I'd vote you down for calling someone else's solution "dumb"...but I don't want to be unwelcoming. Thanks for trying! – Jenn D. May 14 '13 at 20:34