我想在 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";

} 
有帮助吗?

解决方案

嵌套数据结构包含哈希 参考, ,不是哈希值。

# 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:

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

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

您的数组中实际拥有的是 hashref,而不是哈希。如果您不理解这个概念,可能值得阅读 佩尔参考 文档。

得到你需要做的哈希

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 之类的东西。

另请注意,一个好的 Perl 习惯用法是

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

迭代列表。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top