如何在Perl中使用DBI获取列名和行数据?

时间:2010-02-17 17:47:22

标签: 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)

我知道这种情况正在发生,因为我正在使用哈希,但如果我只使用数组,如何才能获得列名?我想做的就是为任何任意查询得到类似的内容:

    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;

5 个答案:

答案 0 :(得分:15)

将“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_lc以小写字母提供字段名称。您也可以使用NAME_uc表示大写,或NAME表示数据库决定将其返回的情况。

您也应该使用Text::CSVText::CSV_XS而不是尝试滚动自己的CSV文件,但这是另一个问题。

答案 1 :(得分:2)

如果您想保留订单,但仍然使用哈希来按名称引用字段:

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

这将为您提供一个有序的哈希数组

答案 2 :(得分:2)

在SELECT

之前的ARRAY中定义列名

理想情况下,您有一个列表,列出了您使用DBI SELECT'ing 的列,并且您将使用该数组。

如果您需要从散列本身获取列名,这将起作用,您可以对其进行排序,但没有指示原始的 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};          

那应该按原始顺序给你列名,但我还没有测试过。

答案 3 :(得分:1)

您要求将结果作为哈希值。哈希本质上是无序的。也许你想要fetchrow_arrayref

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

答案 4 :(得分:1)

这就是我的所作所为:

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