2010-08-26 11 views
8

Tenga en cuenta la siguiente tabla:Perl DBI fetchall_hashref

mysql> select * from vCountryStatus; 
+-------------+------------+------+---------+--------+-----------------+ 
| CountryName | CountryISO | Code | Status | Symbol | CurrencyName | 
+-------------+------------+------+---------+--------+-----------------+ 
| Brazil  | BR   | 55 | LIVE | BRL | Brazilian Real | 
| France  | FR   | 33 | offline | EUR | Euro   | 
| Philippines | PH   | 63 | LIVE | PHP | Philippino Peso | 
+-------------+------------+------+---------+--------+-----------------+ 
3 rows in set (0.00 sec) 

Estoy tratando de construir un hash a partir de esta tabla. Para esto haga lo siguiente:

#!/usr/bin/perl 

use DBI; 
use Data::Dumper; 

my $dbh = DBI->connect("dbi:mysql:database=db", "user", "password", {RaiseError => 1, AutoCommit => 0, FetchHashKeyName => "NAME_lc"}) || die "DB open error: $DBI::errstr"; 

my $sth = $dbh->prepare("select * from vCountryStatus"); 
$sth->execute; 
my $hash = $sth->fetchall_hashref('countryiso'); 
print Dumper($hash); 

Aquí está la salida esto genera:

$VAR1 = { 
      'PH' => { 
        'symbol' => 'PHP', 
        'status' => 'LIVE', 
        'countryname' => 'Philippines', 
        'countryiso' => 'PH', 
        'currencyname' => 'Philippino Peso', 
        'code' => '63' 
        }, 
      'BR' => { 
        'symbol' => 'BRL', 
        'status' => 'LIVE', 
        'countryname' => 'Brazil', 
        'countryiso' => 'BR', 
        'currencyname' => 'Brazilian Real', 
        'code' => '55' 
        }, 
      'FR' => { 
        'symbol' => 'EUR', 
        'status' => 'offline', 
        'countryname' => 'France', 
        'countryiso' => 'FR', 
        'currencyname' => 'Euro', 
        'code' => '33' 
        } 
     }; 

La pregunta es: ¿por qué es la clave de la almohadilla (countryiso) se repite en los valores dentro del hash?

Lo que yo prefiero es el siguiente resultado:

$VAR1 = { 
      'PH' => { 
        'symbol' => 'PHP', 
        'status' => 'LIVE', 
        'countryname' => 'Philippines', 
        'currencyname' => 'Philippino Peso', 
        'code' => '63' 
        }, 
      'BR' => { 
        'symbol' => 'BRL', 
        'status' => 'LIVE', 
        'countryname' => 'Brazil', 
        'currencyname' => 'Brazilian Real', 
        'code' => '55' 
        }, 
      'FR' => { 
        'symbol' => 'EUR', 
        'status' => 'offline', 
        'countryname' => 'France', 
        'currencyname' => 'Euro', 
        'code' => '33' 
        } 
     }; 

¿Es posible utilizar el método de DBI fetchall_hashref? ¿O debo seguir el camino tradicional, recorriendo cada fila y construyendo el hash sobre la marcha?

+1

FYI, el preparar, ejecutar y llamadas fetchall_hashref se pueden contraer en una sola llamada selectall_hashref, como esto: mi $ = $ hash de dbh-> selectall_hashref '("select * from vCountryStatus", "countryiso ');' –

+0

si hay otra fila con el valor CountryISO como PH, entonces se imprimirán ambas filas, de lo contrario, ¿cómo imprimir todas las filas con la misma clave? – Lucy

Respuesta

3

No, no se puede hacer usando fetchall_hashref. Pero se puede iterar sobre los valores de hash y elimine la clave:

delete $_->{countryiso} for values %$hash; 
+0

Gracias, eso es lo que esperaba. No es un gran problema, ya que dijiste que podía eliminarlos u otra solución sería ignorarlos ya que la carga adicional de memoria (en mi caso) sería muy pequeña. – emx

+0

si hay otra fila con el valor de CountryISO como PH, entonces se imprimirán ambas filas ??? si no, ¿cómo se imprimirán todas las filas con la misma clave? ¿Se usará while loop? – Lucy

1

Tuve este mismo problema, pero estaba usando varias claves en fetchall_hashref, así que tuve que ir más profundo en las referencias de patata. No es exactamente la ciencia de cohetes, pero aquí está:

(...)   
      my @keys=('key1','key2','key3'); 
      my $result_ref=$sth->fetchall_hashref(\@keys); 

      remove_key_values($result_ref,\@keys); 
(...) 


sub remove_key_values { 
    my ($href_values,$aref_keys) = (@_); 

    foreach my $hk (keys %$href_values) { 
     foreach my $ak (@$aref_keys) { 
      if ($ak eq $hk) { 
       delete $href_values->{$hk}; 
      } 
     } 
     if (exists $href_values->{$hk} and ref($href_values->{$hk}) eq 'HASH') { 
       remove_key_values($href_values->{$hk},$aref_keys); 
     } 
    } 
} 
Cuestiones relacionadas