Domanda

Voglio scrivere una piccola funzione "DBQuery" in Perl in modo da poter avere una riga che invia un'istruzione SQL e riceve indietro e una serie di hash, ad es.un recordset.Tuttavia, sto riscontrando un problema con la sintassi Perl (e probabilmente qualche strano problema con puntatori/riferimenti) che mi impedisce di estrarre le informazioni dall'hash che ricevo dal database.Il codice di esempio riportato di seguito illustra il problema.

Posso ottenere i dati "Jim" da un hash all'interno di un array con questa sintassi:

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

restituisce "Jim"

ma se copio prima il record hash nell'array nella sua variabile hash, stranamente non riesco più ad accedere ai dati in quell'hash:


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

restituisce "" (vuoto)

Ecco il codice di esempio completo che mostra il problema.Qualsiasi aiuto è apprezzato:


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

} 
È stato utile?

Soluzione

La struttura dati annidata contiene un hash riferimento, non un 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";

Se ti viene mai presentata una struttura dati Perl profonda, potresti trarre profitto stampandola utilizzando Dati::Dumper per stamparlo in un formato leggibile dall'uomo (e analizzabile in Perl).

Altri suggerimenti

L'array di hash in realtà non contiene hash, ma piuttosto un file Riferimenti ad un hash.Questa riga:

%row = $records[$index];

assegna %row con una voce.La chiave è la scalare:

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

Che è un riferimento all'hash, mentre il valore è vuoto.

Quello che vuoi veramente fare è questo:

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

o altro:

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

Altri hanno commentato hash vs hashref.Un'altra cosa che ritengo debba essere menzionata è la tua funzione DBQuery: sembra che tu stia cercando di fare qualcosa che è già integrato nel DBI?Se ho capito bene la tua domanda, stai cercando di replicare qualcosa del genere selectall_arrayref:

Questo metodo di utilità combina "prepare", "execute" e "fetchall_arrayref" in un'unica chiamata.Restituisce un riferimento a un array contenente un riferimento a un array (o hash, vedi sotto) per ogni riga di dati recuperata.

Per aggiungere alle adorabili risposte di cui sopra, lasciami aggiungere che dovresti sempre, sempre, sempre (sì, tre "sempre") utilizzare "usa avvisi" nella parte superiore del codice.Se lo avessi fatto, avresti ricevuto l'avviso "Riferimento trovato dove era previsto un elenco di dimensioni pari in -e riga 1".

quello che hai effettivamente nel tuo array è un hashref, non un hash.Se non capisci questo concetto, probabilmente vale la pena leggere il perlrif documentazione.

per ottenere l'hash che devi fare

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

Per esempio.

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

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

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

Sebbene.Non sono sicuro del motivo per cui vorresti farlo, a meno che non sia per scopi accademici.Altrimenti, consiglierei fetchall_hashref/fetchall_arrayref nel modulo DBI o utilizzare qualcosa come Class::DBI.

Nota anche che un buon idioma Perl da usare è

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

per scorrere l'elenco.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top