Pergunta

Quero escrever uma pequena função "DBQuery" em perl para que possa ter one-liners que enviem uma instrução SQL e recebam de volta uma matriz de hashes, ou seja,um conjunto de registros.No entanto, estou tendo um problema com a sintaxe Perl (e provavelmente algum problema estranho de ponteiro/referência) que está me impedindo de empacotar as informações do hash que estou obtendo do banco de dados.O código de exemplo abaixo demonstra o problema.

Posso obter os dados "Jim" de um hash dentro de um array com esta sintaxe:

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

retorna "Jim"

mas se eu copiar primeiro o registro hash na matriz para sua própria variável hash, estranhamente não poderei mais acessar os dados nesse hash:


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

retorna "" (em branco)

Aqui está o código de exemplo completo mostrando o problema.Qualquer ajuda é apreciada:


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

} 
Foi útil?

Solução

A estrutura de dados aninhada contém um hash referência, não um 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 alguma vez lhe for apresentada uma estrutura de dados Perl profunda, você poderá lucrar imprimindo-a usando Dados::Dumper para imprimi-lo em formato legível por humanos (e analisável por Perl).

Outras dicas

A matriz de hashes na verdade não contém hashes, mas sim um referências para um hash.Está linha:

%row = $records[$index];

atribui% linha com uma entrada.A chave é o escalar:

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

Que é uma referência ao hash, enquanto o valor está em branco.

O que você realmente quer fazer é isto:

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

se não:

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

Outros comentaram sobre hashes versus hashrefs.Outra coisa que acho que deveria ser mencionada é a sua função DBQuery - parece que você está tentando fazer algo que já está embutido no DBI?Se entendi sua pergunta corretamente, você está tentando replicar algo como selectall_arrayref:

Este método utilitário combina "prepare", "execute" e "fetchall_arrayref" em uma única chamada.Ele retorna uma referência a um array contendo uma referência a um array (ou hash, veja abaixo) para cada linha de dados buscada.

Para complementar as lindas respostas acima, deixe-me acrescentar que você deve sempre, sempre, sempre (sim, três "sempre") usar "use warnings" no topo do seu código.Se você tivesse feito isso, teria recebido o aviso "Referência encontrada onde a lista de tamanho par é esperada na -e linha 1".

o que você realmente tem em seu array é um hashref, não um hash.Se você não entende esse conceito, provavelmente vale a pena ler o perlref documentação.

para obter o hash que você precisa fazer

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

Por exemplo.

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

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

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

Embora.Não sei por que você faria isso, a menos que seja para fins acadêmicos.Caso contrário, eu recomendaria fetchall_hashref/fetchall_arrayref no módulo DBI ou usar algo como Class::DBI.

Observe também que um bom idioma Perl para usar é

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

para iterar pela lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top