¿Cómo puedo obtener los nombres de las columnas y los datos de las filas en orden con DBI en Perl?
sqlite3 (5)
Estás pidiendo el resultado como un hash. Un hash es inherentemente desordenado. Quizás quieras fetchrow_arrayref
en fetchrow_arrayref
lugar.
De hecho, si hubieras analizado las keys %$row
, también habrías visto las claves correspondientes fuera de servicio. 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.
Estoy usando DBI para consultar una base de datos SQLite3. Lo que tengo funciona, pero no devuelve las columnas en orden. Ejemplo:
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 forma obtengo los nombres de las columnas si solo uso una matriz? Todo lo que quiero hacer es obtener algo como esto para cualquier consulta arbitraria :
col1, col2, col3, col4
1, 2, 3, 4
1, 2, 3, 4
1, 2, 3, 4
1, 2, 3, 4
...
(Es decir, necesito que la salida esté en el orden correcto y con los nombres de las columnas).
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 estoy buscando 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;
Reemplace el comentario "lo que sucede aquí" y el siguiente 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
proporciona los nombres de los campos en minúsculas. También puede usar NAME_uc
para mayúsculas o NAME
para el caso en que la base de datos decida devolverlos.
También debería usar Text :: CSV o Text :: CSV_XS en lugar de intentar rodar su propio archivo CSV, pero esa es otra cuestión.
Si desea conservar el pedido, pero aún usar un hash para referirse a los campos por nombre, use:
$dbh->selectall_arrayref($sql,{ Slice => {} } );
Esto te dará una matriz ordenada de hashes
Defina los nombres de sus columnas en un ARRAY antes de su SELECCIONAR
Idealmente, tendría una lista de las columnas que estaba SELECCIONANDO con DBI, y usaría esa matriz.
Si necesita obtener los nombres de las columnas del hash, esto funcionará, y puede ordenarlo, pero no hay indicación del orden SQL SELECT original (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é, encontré una forma de obtener los nombres de columna de 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};
Eso debería darte los nombres de las columnas en el orden original, pero no lo he probado.
Esto 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);