简体   繁体   中英

Perl Array Dereference Problem with DBI::fetchall_arrayref

I'm a Perl newbie and am having issues with dereferencing an array that is a result of fetchall_arrayref in the DBI module:

my $sql = "SELECT DISTINCT home_room FROM $classlist";
my $sth = $dbh->prepare($sql);
$sth->execute;
my $teachers = $sth->fetchall_arrayref;
foreach my $teacher (@{$teachers}) {
    print $teacher;
}

Running this will print the reference instead of the values in the array.

However, when I run:

my $arrref = [1,2,4,5];
foreach (@{$arrref}) {
print "$_\n";
}

I get the values of the array.

What am I doing wrong? Thank you for your help!

Jeff

From the doc

The fetchall_arrayref method can be used to fetch all the data to be returned from a prepared and executed statement handle. It returns a reference to an array that contains one reference per row .

So in your example, $teacher is an ARRAY ref. So you will need to loop through this array ref

foreach my $teacher (@{$teachers}) {
    foreach my $titem (@$teacher) {
        print $titem;
    }
}

如果您只想提取教师列,则可以使用:

my @teachers = @{$dbh->selectcol_arrayref($sql)};

fetchall_arrayref fetches all the results of the query, so what you're actually getting back is a reference to an array of arrays. Each row returned will be an arrayref of the columns. Since your query has only one column, you can say:

my $teachers = $sth->fetchall_arrayref;
foreach my $teacher (@{$teachers}) {
    print $teacher->[0];
}

to get what you want.

See more:

Arrays of arrays in Perl .

You have a reference to an array of rows. Each row is a reference to an array of fields.

foreach my $teacher_row (@$teachers) {
    my ($home_room) = @$teacher_row;
    print $home_room;
}

You would have seen the difference with Data::Dumper .

use Data::Dumper;
print(Dumper($teachers));
print(Dumper($arrref));

$sth->fetchall_arrayref returns a reference to an array that contains one reference per row!
Take a look at DBI docs here .

Per the documentation of DBI's fetchall_arrayref() :

The fetchall_arrayref method can be used to fetch all the data to be returned from a prepared and executed statement handle. It returns a reference to an array that contains one reference per row.

You're one level of indirection away:

my $sql = "SELECT DISTINCT home_room FROM $classlist";
my $sth = $dbh->prepare($sql);
$sth->execute;
my $teachers = $sth->fetchall_arrayref;
foreach my $teacher (@{$teachers}) {
    local $" = ', ';
    print "@{$teacher}\n";
}

The data structure might be a little hard to visualize sometimes. When that happens I resort to Data::Dumper so that I can insert lines like this:

print Dumper $teacher;

I've found that sometimes by dumping the datastructure I get an instant map to use as a reference-point when creating code to manipulate the structure. I recently worked through a real nightmare of a structure just by using Dumper once in awhile to straighten my head out.

You can use map to dereference the returned structure:

@teachers = map { @$_->[0] } @$teachers;

Now you have a simple array of teachers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM