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 $开发者_JS百科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;
}
}
if you want to extract only the teacher column, you want to use:
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.
精彩评论