2010-02-17 11 views
13

Sto utilizzando DBI per interrogare un database SQLite3. Quello che ho funziona, ma non restituisce le colonne in ordine. Esempio:Come posso ottenere i nomi delle colonne e i dati delle righe in ordine con DBI in Perl?

Query: select col1, col2, col3, col4 from some_view; 
Output: 

    col3, col2, col1, col4 
    3, 2, 1, 4 
    3, 2, 1, 4 
    3, 2, 1, 4 
    3, 2, 1, 4 
    ... 

(values and columns are just for illustration) 

So che questo sta accadendo perché sto utilizzando un hash, ma in quale altro modo ottengo i nomi delle colonne indietro se io uso solo un array? Tutto quello che voglio fare è ottenere qualcosa di simile per qualsiasi richiesta arbitraria:

col1, col2, col3, col4 
    1, 2, 3, 4 
    1, 2, 3, 4 
    1, 2, 3, 4 
    1, 2, 3, 4 
    ... 

(Cioè, mi serve l'uscita è nel giusto ordine e con i nomi delle colonne.)

I' Sono molto un novizio Perl, ma ho davvero pensato che sarebbe stato un problema semplice. (L'ho già fatto in Ruby e PHP, ma ho problemi a rintracciare ciò che sto cercando nella documentazione Perl.)

Ecco una versione ridotta di ciò che ho al momento:

use Data::Dumper; 
use DBI; 

my $database_path = '~/path/to/db.sqlite3'; 

$database = DBI->connect(
    "dbi:SQLite:dbname=$database_path", 
    "", 
    "", 
    { 
    RaiseError => 1, 
    AutoCommit => 0, 
    } 
) or die "Couldn't connect to database: " . DBI->errstr; 

my $result = $database->prepare('select col1, col2, col3, col4 from some_view;') 
    or die "Couldn't prepare query: " . $database->errstr; 

$result->execute 
    or die "Couldn't execute query: " . $result->errstr; 

########################################################################################### 
# What goes here to print the fields that I requested in the query? 
# It can be totally arbitrary or '*' -- "col1, col2, col3, col4" is just for illustration. 
# I would expect it to be called something like $result->fields 
########################################################################################### 

while (my $row = $result->fetchrow_hashref) { 
    my $csv = join(',', values %$row); 
    print "$csv\n"; 
} 

$result->finish; 

$database->disconnect; 
+0

Spiacente, non so perché questa scese votato. Si prega di lasciare un commento se si pensa che potrebbe essere migliorato. –

risposta

15

Sostituire il "cosa va qui" commento e il seguente ciclo con:

my $fields = join(',', @{ $result->{NAME_lc} }); 
print "$fields\n"; 

while (my $row = $result->fetchrow_arrayref) { 
    my $csv = join(',', @$row); 
    print "$csv\n"; 
} 

NAME_lc dà i nomi dei campi in minuscolo. È inoltre possibile utilizzare NAME_uc per la lettera maiuscola, o NAME per qualsiasi caso il database decide di restituirli in.

Si dovrebbe anche probabilmente utilizzando Text::CSV o Text::CSV_XS invece di cercare di rotolare il proprio file CSV, ma questa è un'altra questione.

+0

Fantastico, ci proverò. Vorrei usare Text :: CSV, ma al momento sto stampando l'output solo a scopo di test. –

+0

Ha funzionato alla grande. Grazie ancora. Non c'è da stupirsi che non sia venuto fuori quando ho cercato: Google soffoca su cose come '@ {$ result -> {NOME}}'. –

+1

Bene, il posto da cercare è http://search.cpan.org/perldoc?DBI (o la tua copia locale). – cjm

1

Stai chiedendo il risultato come un hash. Un hash è intrinsecamente non ordinato. Forse vuoi fetchrow_arrayref invece.

Infatti, se avessi guardato a keys %$row, avresti visto che anche le chiavi corrispondenti erano fuori uso. Questa è la natura di un hash ... ogni chiave è abbinata al suo valore, ma l'ordine generale di chiavi o valori è ottimizzato per l'accesso, non per l'ordine esterno.

+0

Dalla domanda: "So che questo sta accadendo perché sto usando un hash, ma in quale altro modo ottengo i nomi delle colonne se uso solo un array?" È l'ultima parte con cui sto avendo un problema. –

+1

Vedere "Attributi handle di istruzione" nel documento DBI. –

+0

Da quello che ho letto in Perl, le funzioni "chiavi" e "valori" che agiscono sullo stesso hash garantiscono lo stesso ordinamento di elementi negli array corrispondenti restituiti. Quindi un trucco sarebbe quello di recuperare la prima riga, afferrare i nomi dei campi, quindi continuare l'elaborazione del resto delle righe. – jerseyboy

2

Se si desidera mantenere l'ordine, ma ancora usare un hash per fare riferimento ai campi per nome uso:

$dbh->selectall_arrayref($sql,{ Slice => {} }); 

questo vi darà un array ordinato di hash

2

Definire i nomi delle colonne in un ARRAY prima del SELEZIONA

Idealmente avresti una lista delle colonne che eri SELEZIONA con DBI, e dovresti usare quell'array.

Se avete bisogno di ottenere i nomi delle colonne del hash per sé, questo sistema funziona, e si può ordinare, ma non c'è alcuna indicazione dell'originale SQL SELECT ordine (nel hash):

my %cols_hash = ("name" => "john", "age" => 2, "color" => "apalachian"); 
my $cols_hash_ref = \%cols; 

my @keys = (sort keys %$cols_hash_ref); 
my @vals; 
foreach (@keys){ push @vals, $$cols_hash_ref{$_} }; 

Spero che questo aiuti.

Quando ho cercato ho trovato un modo per ottenere i nomi delle colonne dalla DBI:

$sth = $dbh->prepare($query) or die "Prepare exceptioin: $DBI::errstr!"; 
$rv = $sth->execute() or die "Execute exception: $DBI::errstr"; 
$res = $sth->fetchall_arrayref(); 

# Array reference with cols captions, which were retrived. 
$col_names_array_ref = $sth->{NAME};   

Questo dovrebbe darvi i nomi delle colonne nell'ordine originale, ma non ho provato.

1

Ecco quello che faccio:

use Data::Dump qw(dump); 
    # get column names in array 
    my @column_names_array= $sth->{NAME}; 
    # print out column names in pretty format 
    print "Field names: \n"; 
    dump(@column_names_array); 
+0

Bene ... questa è una semplice illustrazione. Grazie! –

Problemi correlati