Frage

Ich möchte eine kleine „DBQuery“-Funktion in Perl schreiben, damit ich Einzeiler haben kann, die eine SQL-Anweisung senden und zurückerhalten, sowie ein Array von Hashes, d. h.ein Datensatz.Allerdings stoße ich auf ein Problem mit der Perl-Syntax (und wahrscheinlich auf ein seltsames Zeiger-/Referenzproblem), das mich daran hindert, die Informationen aus dem Hash herauszupacken, den ich aus der Datenbank erhalte.Der folgende Beispielcode veranschaulicht das Problem.

Mit dieser Syntax kann ich die Daten „Jim“ aus einem Hash in einem Array abrufen:

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

gibt „Jim“ zurück

aber wenn ich den Hash-Datensatz im Array zuerst in seine eigene Hash-Variable kopiere, kann ich seltsamerweise nicht mehr auf die Daten in diesem Hash zugreifen:


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

gibt „“ (leer) zurück

Hier ist der vollständige Beispielcode, der das Problem zeigt.Jede Hilfe ist willkommen:


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

} 
War es hilfreich?

Lösung

Die verschachtelte Datenstruktur enthält einen Hash Referenz, kein 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";

Wenn Sie jemals mit einer tiefen Perl-Datenstruktur konfrontiert werden, können Sie davon profitieren, diese mit auszudrucken Daten::Dumper um es in für Menschen lesbarer (und perl-parsabler) Form auszudrucken.

Andere Tipps

Das Hash-Array enthält eigentlich keine Hashes, sondern einen Verweise zu einem Hash.Diese Linie:

%row = $records[$index];

weist %row einen Eintrag zu.Der Schlüssel ist der Skalar:

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

Dies ist ein Verweis auf den Hash, während der Wert leer ist.

Was Sie wirklich tun möchten, ist Folgendes:

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

oder aber:

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

Andere haben sich zu Hashes vs. Hashrefs geäußert.Eine andere Sache, die meiner Meinung nach erwähnt werden sollte, ist Ihre DBQuery-Funktion. Anscheinend versuchen Sie, etwas zu tun, das bereits in die DBI integriert ist?Wenn ich Ihre Frage richtig verstehe, versuchen Sie so etwas zu reproduzieren selectall_arrayref:

Diese Utility-Methode kombiniert „prepare“, „execute“ und „fetchall_arrayref“ in einem einzigen Aufruf.Es gibt einen Verweis auf ein Array zurück, das für jede abgerufene Datenzeile einen Verweis auf ein Array (oder einen Hash, siehe unten) enthält.

Um die schönen Antworten oben zu ergänzen, möchte ich hinzufügen, dass Sie immer, immer, immer (ja, drei „immer“) „Warnungen verwenden“ oben in Ihrem Code verwenden sollten.Wenn Sie dies getan hätten, hätten Sie die Warnung „Referenz gefunden, wo in -e Zeile 1 eine Liste mit gerader Größe erwartet wird“ erhalten.

Was Sie tatsächlich in Ihrem Array haben, ist ein Hashref, kein Hash.Wenn Sie dieses Konzept nicht verstehen, lohnt es sich wahrscheinlich, es zu lesen perlref Dokumentation.

Um den Hash zu erhalten, müssen Sie Folgendes tun

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

Z.B.

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

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

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

Obwohl.Ich bin mir nicht sicher, warum Sie das tun sollten, es sei denn, es dient akademischen Zwecken.Ansonsten würde ich entweder fetchall_hashref/fetchall_arrayref im DBI-Modul empfehlen oder etwas wie Class::DBI verwenden.

Beachten Sie auch, dass eine gute Perl-Sprache verwendet werden kann

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

um die Liste zu durchlaufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top