2010-02-17 19 views
13

Estoy usando DBI para consultar una base de datos SQLite3. Lo que tengo funciona, pero no devuelve las columnas en orden. Ejemplo:¿Cómo puedo obtener los nombres de las columnas y los datos de las filas en orden con DBI en 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) 

Sé que esto está sucediendo porque estoy usando un hash, pero de qué otra manera puedo obtener los nombres de las columnas del artículo si sólo utilizo una matriz? Todo lo que quiero hacer es obtener algo como esto para cualquier arbitraria consulta:

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

(Es decir, necesito la salida está en el orden correcto y con los nombres de las columnas.)

I' Soy un principiante de Perl, pero realmente pensé que sería un problema simple. (He hecho esto antes en Ruby y PHP, pero tengo problemas para encontrar lo que busco en la documentación de Perl.)

Aquí hay una versión simplificada de lo que tengo en este 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

Lo sentimos, no está seguro de por qué esto se bajó votó. Por favor, deje un comentario si cree que podría mejorarse. –

Respuesta

15

Reemplazar el "qué va aquí" comentario y el siguiente bucle 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 da los nombres de los campos en minúsculas. También puede utilizar NAME_uc de mayúsculas o NAME por cualquier caso, la base de datos decide devolver el producto en.

También debe probablemente a utilizar Text::CSV o Text::CSV_XS lugar de tratar de rodar su propio archivo CSV, pero eso es otra cuestión.

+0

Genial, lo intentaré. Usaría Text :: CSV, pero solo estoy imprimiendo el resultado para fines de prueba en este momento. –

+0

Funcionó muy bien. Gracias de nuevo. No me extraña que no apareciera cuando busqué: Google se ahoga en cosas como '@ {$ result -> {NAME}}'. –

+1

Bueno, el lugar para buscar es http://search.cpan.org/perldoc?DBI (o su copia local). – cjm

1

Está pidiendo el resultado como hash. Un hash es inherentemente desordenado. Quizás desee fetchrow_arrayref en su lugar.

De hecho, si hubiera mirado keys %$row, también habría visto que las teclas correspondientes estaban desordenadas. Esa es la naturaleza de un hash ... cada clave está emparejada con su valor, pero el orden general de las claves o valores está optimizado para el acceso, no para el orden externo.

+0

De la pregunta: "Sé que esto está sucediendo porque estoy usando un hash, pero ¿de qué otra forma puedo recuperar los nombres de las columnas si solo uso una matriz?" Es la última parte con la que tengo un problema. –

+1

Consulte "Atributos del identificador de extracto" en el documento DBI. –

+0

Según lo que he leído en Perl, las funciones de "claves" y "valores" que actúan sobre el mismo hash garantizan que se ordenen de la misma manera los elementos en las matrices correspondientes que devuelven. Entonces, un truco sería buscar la primera fila, tomar los nombres de los campos y continuar procesando el resto de las filas. – jerseyboy

2

Si desea conservar el orden, pero todavía utilizar un hash para referirse a los campos de nombre de uso:

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

esto le dará un conjunto ordenado de valores hash

2

Definir sus nombres de columna en un ARRAY antes de su SELECCIONAR

Lo ideal sería que tuviera una lista de las columnas en las que estaba SELECCIONANDO con DBI, y usaría esa matriz.

Si usted necesita para obtener los nombres de las columnas de la propia hachís, esto va a funcionar, y se puede solucionar el problema, pero no hay ninguna indicación del original SQL SELECT orden (en el 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{$_} }; 

Espero que esto ayude.

Cuando busqué he encontrado una manera de obtener los nombres de las columnas de la 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};   

que usted debe dar los nombres de las columnas en el orden original, pero yo no lo he probado.

1

Aquí es lo que hago:

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

Bueno ... eso es una ilustración simple. ¡Gracias! –

Cuestiones relacionadas