Проблем с дерефериране на Perl масив с DBI::fetchall_arrayref

Аз съм начинаещ в Perl и имам проблеми с дереференцирането на масив, който е резултат от fetchall_arrayref в DBI модула:

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;
}

Изпълнението на това ще отпечата препратката вместо стойностите в масива.

Въпреки това, когато бягам:

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

Получавам стойностите на масива.

какво правя грешно Благодаря ти за помощта!

Джеф


person Jeff Erickson    schedule 22.06.2011    source източник


Отговори (7)


ако искате да извлечете само колоната на учителя, искате да използвате:

my @teachers = @{$dbh->selectcol_arrayref($sql)};
person paul    schedule 22.06.2011

От документ

Методът fetchall_arrayref може да се използва за извличане на всички данни, които трябва да бъдат върнати от подготвен и изпълнен манипулатор на израз. Връща препратка към масив, който съдържа по една препратка на ред.

Така че във вашия пример $teacher е ARRAY ref. Така че ще трябва да преминете през този масив ref

foreach my $teacher (@{$teachers}) {
    foreach my $titem (@$teacher) {
        print $titem;
    }
}
person ccheneson    schedule 22.06.2011

fetchall_arrayref извлича всички резултати от заявката, така че това, което всъщност получавате обратно, е препратка към масив от масиви. Всеки върнат ред ще бъде arrayref от колоните. Тъй като вашата заявка има само една колона, можете да кажете:

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

за да получите това, което искате.

Виж повече:

Масиви от масиви в Perl.

person friedo    schedule 22.06.2011

Имате препратка към масив от редове. Всеки ред е препратка към масив от полета.

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

Щеше да видиш разликата с Data::Dumper.

use Data::Dumper;
print(Dumper($teachers));
print(Dumper($arrref));
person ikegami    schedule 22.06.2011

$sth->fetchall_arrayref връща препратка към масив, който съдържа по една препратка на ред!
Разгледайте DBI документите тук.

person cirne100    schedule 22.06.2011

Според документацията на fetchall_arrayref() на DBI:

Методът fetchall_arrayref може да се използва за извличане на всички данни, които трябва да бъдат върнати от подготвен и изпълнен манипулатор на израз. Връща препратка към масив, който съдържа по една препратка на ред.

Вие сте на едно ниво на индиректност:

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";
}

Понякога структурата на данните може да е малко трудна за визуализиране. Когато това се случи, прибягвам до Data::Dumper, за да мога да вмъкна редове като този:

print Dumper $teacher;

Открих, че понякога чрез изхвърляне на структурата от данни получавам незабавна карта, която да използвам като референтна точка, когато създавам код за манипулиране на структурата. Наскоро преминах през истински кошмар от структура само като използвах Dumper от време на време, за да изправя главата си.

person DavidO    schedule 22.06.2011

Можете да използвате map за дерефериране на върнатата структура:

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

Сега имате прост набор от учители.

person paz9    schedule 27.07.2013
comment
Трябва да спомена, че @ преди $_ ще доведе до отхвърлено предупреждение в по-късните версии на perl. Просто го премахнете, за да заглушите това. - person paz9; 29.07.2013