Как я могу получить имена столбцов и данные строк в DBI в Perl?
Я использую DBI для запроса базы данных SQLite3. У меня есть работы, но он не возвращает столбцы по порядку. Пример:
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)
Я знаю, что это происходит, потому что я использую хеш, но как еще я получу имена столбцов, если я использую только массив? Все, что я хочу сделать, это получить что-то вроде этого для любого произвольного запроса:
col1, col2, col3, col4
1, 2, 3, 4
1, 2, 3, 4
1, 2, 3, 4
1, 2, 3, 4
...
(То есть, мне нужен вывод в правильном порядке и с именами столбцов.)
Я очень новичок в Perl, но я действительно думал, что это будет простая проблема. (Я делал это раньше в Ruby и PHP, но у меня возникают проблемы с отслеживанием того, что я ищу в документации Perl.)
Вот сводная версия того, что у меня есть на данный момент:
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;
Ответы
Ответ 1
Замените комментарий "что здесь происходит" и следующий цикл:
my $fields = join(',', @{ $result->{NAME_lc} });
print "$fields\n";
while (my $row = $result->fetchrow_arrayref) {
my $csv = join(',', @$row);
print "$csv\n";
}
NAME_lc
дает имена полей в нижнем регистре. Вы также можете использовать NAME_uc
для верхнего регистра или NAME
для любого случая, когда база данных решает вернуть их.
Вероятно, вы также должны использовать Text::CSV или Text::CSV_XS вместо того, чтобы пытаться свернуть собственный CSV файл, но этот еще один вопрос.
Ответ 2
Если вы хотите сохранить заказ, но все равно используйте хеш для обозначения полей по имени, используйте:
$dbh->selectall_arrayref($sql,{ Slice => {} } );
Это даст вам упорядоченный массив хэшей
Ответ 3
Определите имена столбцов в ARRAY перед вашим SELECT
В идеале у вас будет список столбцов, которые вы выбрали с помощью DBI, и вы будете использовать этот массив.
Если вам нужно получить имена столбцов из самого хеша, это будет работать, и вы можете его отсортировать, но нет указаний на исходный порядок SQL SELECT (в хеше):
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{$_} };
Надеюсь, что это поможет.
Когда я искал, я нашел способ получить имена столбцов из 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};
Это должно дать вам имена столбцов в исходном порядке, но я его не тестировал.
Ответ 4
Вы запрашиваете результат как хэш. Хэш по своей сути неупорядочен. Возможно, вы хотите вместо fetchrow_arrayref
.
На самом деле, если вы посмотрели на keys %$row
, вы бы увидели, что соответствующие ключи тоже не в порядке. Что характер хеша... каждая клавиша сопряжена с ее значением, но общий порядок ключей или значений оптимизирован для доступа, а не внешнего порядка.
Ответ 5
Вот что я делаю:
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);