Take the 2-minute tour ×

I want to write a little "DBQuery" function in perl so I can have one-liners which send an SQL statement and receive back and an array of hashes, i.e. a recordset. However, I'm running into an issue with Perl syntax (and probably some odd pointer/reference issue) which is preventing me from packing out the information from the hash that I'm getting from the database. The sample code below demonstrates the issue.

I can get the data "Jim" out of a hash inside an array with this syntax:

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

returns "Jim"

but if I copy the hash record in the array to its own hash variable first, then I strangely can't access the data anymore in that hash:

    %row = $records[$index];

returns "" (blank)

Here is the full sample code showing the problem. Any help is appreciated:

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++) {

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

share|improve this question

6 Answers 6

up vote 19 down vote accepted

The nested data structure contains a hash reference, not a hash.

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

If you're ever presented with a deep Perl data structure, you may profit from printing it using Data::Dumper to print it into human-readable (and Perl-parsable) form.

share|improve this answer
If you ever need to explictly dereference a reference then %{$row} will work, which can be useful sometimes to ensure you're passing the right thing to the right sort of thing. –  Free Wildebeest Sep 14 '08 at 23:51

The array of hashes doesn't actually contain hashes, but rather an references to a hash. This line:

%row = $records[$index];

assigns %row with one entry. The key is the scalar:


Which is a reference to the hash, while the value is blank.

What you really want to do is this:

$row = $records[$index];

or else:

$row = %{$records[$index];}
share|improve this answer
That last bit of code makes no sense. It should be something like: %row=%{$records[$index]}; print $row{'firstName'}; –  Peter Stuifzand Sep 16 '08 at 14:11

Others have commented on hashes vs hashrefs. One other thing that I feel should be mentioned is your DBQuery function - it seems you're trying to do something that's already built into the DBI? If I understand your question correctly, you're trying to replicate something like selectall_arrayref:

This utility method combines "prepare", "execute" and "fetchall_arrayref" into a single call. It returns a reference to an array containing a reference to an array (or hash, see below) for each row of data fetched.

share|improve this answer

To add to the lovely answers above, let me add that you should always, always, always (yes, three "always"es) use "use warnings" at the top of your code. If you had done so, you would have gotten the warning "Reference found where even-sized list expected at -e line 1."

share|improve this answer

what you actually have in your array is a hashref, not a hash. If you don't understand this concept, its probably worth reading the perlref documentation.

to get the hash you need to do

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


my @records = (

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

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

Although. I'm not sure why you would want to do this, unless its for academic purposes. Otherwise, I'd recommend either fetchall_hashref/fetchall_arrayref in the DBI module or using something like Class::DBI.

share|improve this answer
@records[$index] better written as $records[$index] –  Francisco Zarabozo Jun 3 at 5:40

Also note a good perl idiom to use is

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

to iterate through the list.

share|improve this answer

Your Answer


