14

我想在 perl 中编写一个小的“DBQuery”函数,这样我就可以有一个发送 SQL 语句并接收回的单行程序和一个哈希数组,即一个记录集。但是,我遇到了 Perl 语法问题(可能还有一些奇怪的指针/引用问题),这使我无法从从数据库中获取的哈希中打包信息。下面的示例代码演示了该问题。

我可以使用以下语法从数组内的哈希中获取数据“Jim”:

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

} 
4

6 回答 6

23

嵌套数据结构包含哈希引用,而不是哈希。

# 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 数据结构,您可能会受益于使用Data::Dumper将其打印成人类可读(和 Perl 可解析)的形式。

于 2008-09-09T04:03:09.247 回答
5

哈希数组实际上并不包含哈希,而是对哈希的引用。这一行:

%row = $records[$index];

为 %row 分配一个条目。关键是标量

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

这是对哈希的引用,而值为空白。

你真正想做的是:

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

要不然:

$row = %{$records[$index];}
$row{'firstName'};
于 2008-09-09T04:08:39.093 回答
4

其他人评论了哈希与哈希引用。我觉得应该提到的另一件事是您的 DBQuery 功能 - 似乎您正在尝试做一些已经内置在 DBI 中的事情?如果我正确理解您的问题,您正在尝试复制类似selectall_arrayref 的内容

此实用程序方法将“prepare”、“execute”和“fetchall_arrayref”组合到一个调用中。它返回对数组的引用,其中包含对获取的每一行数据的数组(或哈希,见下文)的引用。

于 2008-09-09T06:48:39.740 回答
3

为了添加上面可爱的答案,让我补充一点,您应该始终、始终、始终(是的,三个“始终”)在代码顶部使用“使用警告”。如果您这样做了,您将收到警告“参考在 -e 第 1 行预期的偶数大小列表中找到”。

于 2008-09-09T23:33:44.783 回答
1

你在你的数组中实际拥有的是一个 hashref,而不是一个散列。如果您不理解这个概念,可能值得阅读perlref文档。

得到你需要做的哈希

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

例如。

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

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

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

虽然。我不确定您为什么要这样做,除非出于学术目的。否则,我建议在 DBI 模块中使用 fetchall_hashref/fetchall_arrayref 或使用 Class::DBI 之类的东西。

于 2008-09-09T04:05:10.007 回答
0

还要注意一个好的 perl 习惯用法是

对于我的 $rowHR (@records) {
   我的 %row = %$rowHR;
   #管他呢...
}

遍历列表。

于 2008-09-16T09:22:17.283 回答