Massyn has asked for the wisdom of the Perl Monks concerning the following question:

#!/fellow/monks.pl

I'm busy with a generic SQL2HTML script, using DBI. Using fetchrow_array(), I can query the rows being passed back, and that works great. I would like to populate the top of the table with the field names. How can I get it through DBI? Somehow I keep on missing it in the DBI doco's.

Thanks!

#!/massyn.pl The early worm gets caught by the bird.

Replies are listed 'Best First'.
Re: Field names from DBI?
by adrianh (Chancellor) on Jun 10, 2003 at 11:03 UTC

    Take a look at the NAME statement variable. From the DBI docs.

    "NAME" (array-ref, read-only) Returns a reference to an array of field names for each column. The names may contain spaces but should not be truncated or have any trailing space. Note that the names have the letter case (upper, lower or mixed) as returned by the driver being used. Portable appli- cations should use "NAME_lc" or "NAME_uc". print "First column name: $sth->{NAME}->[0]\n";
Re: Field names from DBI?
by Lachesis (Friar) on Jun 10, 2003 at 11:13 UTC
    To get the table field names you can do the following
    my $sth = $dbh->prepare("SELECT * FROM $tablename WHERE 1=0"); $sth->execute(); my $fields = $sth->{NAME};
    $dbh should be your connected DB handle
    $fields will be an arrayref of the fieldnames
    You can also look at the table_info method but check the docs for your DBD driver to see if its supported
Re: Field names from DBI?
by PodMaster (Abbot) on Jun 10, 2003 at 11:32 UTC
    Heard of DBIx::XHTML_Table ( 1 | 2 )? It's a good wheel ;)


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: Field names from DBI?
by nite_man (Deacon) on Jun 10, 2003 at 11:12 UTC
    It depends of DBD driver which you use.
    This piece of code was tested for PostgreSQL and MYSQL:
    $sth = $dbh->prepare($query) or die "Prepare exceptioin: $DBI::errs +tr!"; $rv = $sth->execute() or die "Execute exception: $DBI::errstr"; $res = $sth->fetchall_arrayref(); # Array reference with cols captions, which were retrived. $names = $sth->{NAME}; # Array reference with types of cols, which were retrived + $types = $sth->{TYPE}; $sth->finish();
    For other database maybe it will be the same
    but try to look at documentation for them DBD drivers.
          
    --------------------------------
    SV* sv_bless(SV* sv, HV* stash);
    
Re: Field names from DBI?
by arthas (Hermit) on Jun 10, 2003 at 11:16 UTC

    adrianh's suggestion is fine. I'll just add that you also have the option to use fetchrow_hashref instead of fetchrow_array: this method returns a refernece to an hash which keys are the field names and values the field values for that row.

    Michele.

      They are not the same thing, though.

      Not only fetchrow_hashref will be slower, because the names are assigned for each row, while $sth->{NAME} is only evaluated once, after the call to "execute," but in addition, if your query contains two columns with the same name, $sth->{NAME} will handle it, but fetchrow_hashref will not.

      select * from dept; select * from emp; +--------+----------+ | deptID | name | +--------+----------+ | 1 | pers | | 2 | sales | | 3 | research | +--------+----------+ +-------+-------+--------+ | empID | name | deptID | +-------+-------+--------+ | 1 | John | 1 | | 2 | Fred | 2 | | 3 | Susan | 2 | +-------+-------+--------+ select distinct dept.deptID, emp.deptID from dept left join emp using(deptID); +--------+--------+ | deptID | deptID | +--------+--------+ | 1 | 1 | | 2 | 2 | | 3 | NULL | +--------+--------+

      Given these tables, the Perl code to handle them could be:

      my $query = qq{select distinct dept.deptID, emp.deptID from dept left join emp using(deptID)}; my $sth = $dbh->prepare($query); $sth->execute(); print "--- names\n"; print join ", ", @{$sth->{NAME}}; print "\n--- fetchrow_hashref\n"; my $row = $sth->fetchrow_hashref(); print "$_ \t" for keys %$row; print "\n"; $sth->finish(); __OUTPUT__ --- names deptID, deptID --- fetchrow_hashref deptID

      Notice that $sth->{NAME}, despite the double names, returns the correct result. fetchrow_hashref, instead, misses one column altogether.

        Thanks cchampion,

        Cool, didn't know that... hmmm, /me "thinks have to go redo some code now". I've been working on a bit of code with a friend to 'clone' an SQL table row, you've just given me a couple of very valuable ideas for improvement... thanks again!

        barrd

      arthas is correct, and here is a bit of (untested) code to do exactly that - though there is undoubtly other (better?) ways to do it.

      my $sql = "SELECT * FROM mytable WHERE foo = bar"; my $sth = $dbh->prepare($sql); $sth->execute() || die $DBI::errstr; my $row = $sth->fetchrow_hashref; my %cols = %$row; # Print the field names print join(', ', sort keys %cols); # Print corresponding values print join(', ', map { defined $cols{$_} ? $dbh->quote($cols{$_}) : 'N +ULL' } sort keys %cols);

      Only posted as a guideline...
      barrd