2010-08-26 100 views
8

考虑下表: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) 

我试图建构基于该表的哈希值。为此,我做到以下几点:

#!/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); 

下面是这个生成输出:

$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' 
        } 
     }; 

的问题是:为什么在哈希内的值,重复的散列(countryiso)的关键?

我宁愿是以下的输出:

$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' 
        } 
     }; 

使用fetchall_hashref DBI方法是否有可能?或者我必须采用传统的方式,循环遍历每一行,并在飞行中构建散列?

+1

仅供参考,准备,执行和fetchall_hashref电话可以折叠成一个单一的selectall_hashref调用,就像这样: '我$哈希= $ dbh-> selectall_hashref( “select * from vCountryStatus”,'countryiso');' – 2012-04-19 12:26:06

+0

如果有另一行的CountryISO值为PH,那么这两行都会被打印出来?如果不是,那么如何打印所有具有相同键的行? – Lucy 2013-05-30 09:41:27

回答

3

不,不能使用fetchall_hashref来完成。但是你可以遍历哈希值和删除键值:

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

谢谢,这正是我期待的。没什么大不了的,正如你所说我可以删除它们,或者另一种解决方案是忽略它们,因为额外的内存开销(在我的情况下)会非常小。 – emx 2010-08-26 09:15:08

+0

如果有另一行的CountryISO值为PH,那么这两行都会被打印???如果没有,那么如何打印所有具有相同键的行?? while while循环被使用? – Lucy 2013-05-30 11:26:17

1

我有同样的问题,但使用上fetchall_hashref多个按键,所以我不得不在哈希引用深究下去。不完全是火箭科学,但在这里它是:

(...)   
      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); 
     } 
    } 
}