如何使用Perl中的DBI按顺序获取列名和行数据?

如何使用Perl中的DBI按顺序获取列名和行数据?,perl,sqlite,dbi,Perl,Sqlite,Dbi,我正在使用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)

我正在使用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;

你要求的结果是散列。散列本质上是无序的。也许您想要
fetchrow\u arrayref

事实上,如果您查看了
keys%$row
,您也会看到相应的键出现了故障。这就是散列的本质。。。每个键都与其值配对,但键或值的整体顺序是针对访问而优化的,而不是外部顺序。

将“what goes here”注释和以下循环替换为:

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

while (my $row = $result->fetchrow_arrayref) {
    my $csv = join(',', @$row);
    print "$csv\n";
}
NAME\u lc
以小写形式给出字段名称。您还可以对大写字母使用
NAME\u uc
,或者对数据库决定返回它们的任何情况使用
NAME


您可能还应该使用或而不是尝试滚动您自己的CSV文件,但这是另一个问题。

如果您想保留顺序,但仍然使用哈希按名称引用字段,请使用:

$dbh->selectall_arrayref($sql,{ Slice => {} } );
这将为您提供一个有序的哈希数组

在选择之前在数组中定义列名 理想情况下,您应该有一个使用DBI选择的列列表,并使用该数组

如果您需要从散列本身获取列名,这将起作用,您可以对其进行排序,但没有指示原始SQL选择顺序(在散列中):

希望这有帮助

搜索时,我找到了一种从DBI获取列名的方法: 这将按原始顺序显示列名,但我尚未对其进行测试。

以下是我的工作:

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

从以下问题中可以看出:“我知道这是因为我使用的是散列,但如果我只使用数组,那么如何才能恢复列名?”这是我遇到的最后一个问题。请参阅“语句句柄属性”从我在Perl中读到的内容来看,作用于同一散列的“key”和“values”函数保证在它们返回的相应数组中给出相同的元素顺序。因此,一个技巧是获取第一行,抓取字段名,然后继续处理其余行。@jerseyboy,只有在调用
之间未修改哈希值时,这才有效。无法保证对
fetchrow\u hashref
的调用之间的结果是一致的。太好了,我试试看。我会使用Text::CSV,但目前我只是出于测试目的打印输出。效果很好。再次感谢。难怪当我搜索时它没有出现——谷歌被
@{$result->{NAME}}
之类的东西堵住了。好吧,搜索的地方是(或你的本地副本)。我遇到了这个问题,但从未在那里找到解决方案。不过,我现在知道该找什么了。很好。。这是一个简单的例子。谢谢
$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};          
    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);