2010-08-26 10 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

FYI, то готовить, выполнять и fetchall_hashref вызовы могут быть свернуты в один вызов selectall_hashref, как это: 'мой $ хеш = $ dbh-> selectall_hashref («select * from vCountryStatus», «countryiso»); ' –

+0

, если есть еще одна строка со значением CountryISO в качестве PH, тогда будут ли печататься обе строки, если нет, то как печатать все строки с одинаковым ключом? – Lucy

ответ

3

Нет, это невозможно, используя fetchall_hashref. Но вы можете перебирать значения хэш-функции и удалить ключ:

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

Спасибо, это то, чего я ожидал. Не большое дело, как вы сказали, я могу либо удалить их, либо другое решение будет игнорировать их, поскольку дополнительные накладные расходы памяти (в моем случае) будут очень маленькими. – emx

+0

, если есть еще одна строка со значением CountryISO в качестве PH, тогда будут напечатаны обе строки, если нет, то, как напечатать все строки с таким же ключом, будет ли использоваться цикл while? – Lucy

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