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

ok, i'm retrieving data from a mysql query, and i want to do a foreach loop through it and place it all into a hash (assigning different fields as the key depending on a preset "sort" variable), but this referece to an array of references to arrays of references or whatever is making my head hurt. please help:
# make the query $array_ref = $dbh->selectall_arrayref("SELECT name,height,width,date F +ROM mydatabase"); # drop it all into a hash named %DB foreach $i ($$array_ref) { if($Sort == "byname") { $DB{ $$i[0] } = [ $$i[1],$$i[2],$$i[3] ]; } elsif($Sort == "bydate") { $DB{ $$i[3] } = [ $$i[1],$$i[2],$$i[0] ]; } }
so....what am i screwing up, because i get errors out the wazoo.

Replies are listed 'Best First'.
Re: DBI help, aka confused newbie
by cchampion (Curate) on May 09, 2004 at 18:18 UTC

    Look at DBI Recipes, and you'll find several ways of dealing with hashes.

    Among them there is something like:

    my $sth=$dbh->prepare($query); $sth->execute or die $DBI::errstr; my $array_of_hashes = $sth->fetchall_arrayref({}); for my $href (@$array_of_hashes) { # do something smart with $href }

    HTH

Re: DBI help, aka confused newbie
by Juerd (Abbot) on May 09, 2004 at 19:51 UTC

    foreach $i ($$array_ref) {

    That should be @$array_ref.

    if($Sort == "byname") {

    == should be eq.

    $DB{ $$i[0] } = [ $$i[1],$$i[2],$$i[3] ];

    Good enough, but consider using arrow notation instead: $i->[0].

    Anyway, the same using DBIx::Simple would be:

    %DB = $db -> query('SELECT name, height, width, date FROM mydatabase') -> map_arrays( { byname => 0, bydate => 3 }->{$sort} );
    Or, if you want hashes (easier to use, but not as efficient) and have a $sortby that is 'name' or 'date' (instead of a $sort that is 'byname' or 'bydate'), you can just use:
    %DB = $db -> query('SELECT name, height, width, date FROM mydatabase') -> map_arrays($sortby);

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: DBI help, aka confused newbie
by matija (Priest) on May 09, 2004 at 17:49 UTC
    Personaly, I dislike using the foreach here - I feel the while works better:
    while ($ref=$sth->fetchrow_hashref) {
    Now, since I have a reference to a hash, I can simply access each element by name: $$ref{foo} for foo, etc.
Re: DBI help, aka confused newbie
by TilRMan (Friar) on May 10, 2004 at 09:03 UTC

    You might find Data::Dumper useful for examining what data structure you have. Use fetchrow_arrayref() or fetchrow_hashref() (as others have already suggested) so that you only need to address one row at a time.

    Read the DBI documentation thoroughly. It's lengthy but it'll save you debugging time, especially if you are new to Perl. Copy the examples carefully; Perl is very intolerant to typos. And remember error checking, even though I didn't here.

    #!/usr/bin/perl use strict; use warnings; use DBI; use Data::Dumper; my $Sort = 'bydate'; my %DB; my $dbh = DBI->connect('DBI:Pg:dbname=tilrman'); my $sth = $dbh->prepare('SELECT name,height,width,date FROM foo'); $sth->execute(); while (my $row = $sth->fetchrow_arrayref()) { if ($Sort eq 'byname') { $DB{$row->[0]} = [ @{$row}[1, 2, 3] ]; } elsif ($Sort eq 'bydate') { $DB{$row->[3]} = [ @{$row}[1, 2, 0] ]; } } $sth->finish(); $dbh->disconnect(); print Data::Dumper->Dump([\%DB], ['*DB']);
Re: DBI help, aka confused newbie
by EvanK (Chaplain) on May 13, 2004 at 01:52 UTC
    if i understand what you're asking for, you should be able to use bind_columns and fetch inside a while loop pretty simply:
    # Prepare, execute, and bind to the query my $sth = $dbh->prepare("SELECT name,height,width,date FROM mydatabase +"); $sth->execute; $sth->bind_columns(\$name,\$height,\$width,\$date); my %DB; #iterate through the recordset with fetch while( $sth->fetch() ) { if($Sort eq "byname") { $DB{$name} = [$height, $width, $date]; } elsif($Sort eq "bydate") { $DB{$date} = [$height, $width, $filename]; } }
Re: DBI help, aka confused newbie
by Anonymous Monk on May 10, 2004 at 06:25 UTC
    ok, i've tried many many ways to do it, but i keep getting this peculiar error:
    Can't use string ("1") as a HASH ref while "strict refs" in use at /us +r/local/lib/perl5/site_perl/5.8.3/i386-freebsd/DBI.pm line 511.