Вопрос

Я хочу написать небольшую функцию «DBQuery» на Perl, чтобы у меня были однострочные строки, которые отправляют оператор SQL и получают обратно, а также массив хешей, т.е.набор записей.Однако у меня возникла проблема с синтаксисом Perl (и, возможно, какая-то странная проблема с указателями/ссылками), которая не позволяет мне упаковать информацию из хеша, который я получаю из базы данных.Пример кода ниже демонстрирует проблему.

Я могу получить данные «Джим» из хеша внутри массива с помощью следующего синтаксиса:

print $records[$index]{'firstName'}

возвращает «Джим»

но если я сначала скопирую хеш-запись в массиве в ее собственную хэш-переменную, то, как ни странно, я больше не смогу получить доступ к данным в этом хеше:


    %row = $records[$index];
    $row{'firstName'};

возвращает "" (пусто)

Вот полный пример кода, показывающий проблему.Любая помощь приветствуется:


my @records = (
   {'id' => 1, 'firstName' => 'Jim'},
   {'id' => 2, 'firstName' => 'Joe'}
);
my @records2 = ();

$numberOfRecords = scalar(@records);
print "number of records: " . $numberOfRecords . "\n";
for(my $index=0; $index < $numberOfRecords; $index++) {

   #works
   print 'you can print the records like this: ' . $records[$index]{'firstName'} . "\n";

   #does NOT work
   %row = $records[$index];
   print 'but not like this: ' . $row{'firstName'} . "\n";

} 
Это было полезно?

Решение

Вложенная структура данных содержит хэш ссылка, а не хеш.

# Will work (the -> dereferences the reference)
$row = $records[$index];
print "This will work: ", $row->{firstName}, "\n";

# This will also work, by promoting the hash reference into a hash
%row = %{ $records[$index] };
print "This will work: ", $row{firstName}, "\n";

Если вам когда-либо приходилось сталкиваться с глубокой структурой данных Perl, вы можете распечатать ее, используя Данные::Дампер чтобы распечатать его в удобочитаемой (и анализируемой Perl) форме.

Другие советы

Массив хешей на самом деле содержит не хеши, а скорее Рекомендации в хеш.Эта строка:

%row = $records[$index];

назначает %row с одной записью.Ключом является скаляр:

   {'id' => 1, 'firstName' => 'Jim'},

Это ссылка на хэш, хотя значение пустое.

Что вы действительно хотите сделать, так это:

$row = $records[$index];
$row->{'firstName'};

или еще:

$row = %{$records[$index];}
$row{'firstName'};

Другие прокомментировали хэши и хэш-ссылки.Еще одна вещь, о которой, по моему мнению, следует упомянуть, — это ваша функция DBQuery. Кажется, вы пытаетесь сделать что-то, что уже встроено в DBI?Если я правильно понял ваш вопрос, вы пытаетесь повторить что-то вроде selectall_arrayref:

Этот служебный метод объединяет «подготовку», «выполнение» и «fetchall_arrayref» в один вызов.Он возвращает ссылку на массив, содержащий ссылку на массив (или хэш, см. ниже) для каждой строки извлеченных данных.

В дополнение к прекрасным ответам выше, позвольте мне добавить, что вы должны всегда, всегда, всегда (да, три «всегда») использовать «использовать предупреждения» в верхней части вашего кода.Если бы вы это сделали, вы бы получили предупреждение: «Ссылка найдена там, где ожидается список четного размера в строке -e 1».

на самом деле в вашем массиве есть хэш-ссылка, а не хэш.Если вы не понимаете эту концепцию, возможно, стоит прочитать перлреф документация.

чтобы получить хэш, вам нужно сделать

my %hash = %{@records[$index]};

Например.

my @records = (
     {'id' => 1, 'firstName' => 'Jim'}, 
     {'id' => 2, 'firstName' => 'Joe'}
  );

  my %hash = %{$records[1]};

  print $hash{id}."\n";

Хотя.Я не уверен, зачем вам это делать, если только это не в академических целях.В противном случае я бы рекомендовал либо fetchall_hashref/fetchall_arrayref в модуле DBI, либо использовать что-то вроде Class::DBI.

Также обратите внимание, что хорошая идиома Perl:

for my $rowHR ( @records ) {
   my %row = %$rowHR; 
   #or whatever...
}

для перебора списка.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top