13

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

我知道发生这种情况是因为我使用的是 hash,但是如果我只使用数组,我还能如何取回列名?我想要做的就是为任何任意查询得到类似的东西:

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

6 回答 6

18

将“这里发生了什么”注释和以下循环替换为:

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 文件,但这是另一个问题。

于 2010-02-17T18:15:12.043 回答
3

在 SELECT 之前在 ARRAY 中定义列名

理想情况下,您将拥有一个使用 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};          

那应该以原始顺序为您提供列名,但我尚未对其进行测试。

于 2014-12-18T04:12:43.423 回答
2

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

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

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

于 2014-01-27T06:53:36.953 回答
1

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

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

于 2010-02-17T17:49:33.257 回答
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);
于 2015-06-09T17:35:38.577 回答
0
#!/usr/bin/perl                                                                                                                                                                        
use strict;
use warnings;
use DBI;
my $database = "your_mysqldb";
my $username = "your_dbusername";
my $password = "your_dbpassword";
my $tblename = "your_mysqldbtable";
my $dsn = "DBI:mysql:embedded";
#                                                                                                                                                                                      
my %attr = ( PrintError=>0,   #turn off error reporting via warn()                                                                                                                     
             RaiseError=>1);  #turn on error reporting via die()                                                                                                                       
my $dbh = DBI->connect($dsn,$username,$password,\%attr);
print "Connected to the MySQL database $database for username $username\n";
my $sql = "DESCRIBE ".$tblename;
my $sth = $dbh->prepare($sql);  
$sth->execute();   #execute the prepared query                                                                                                                                         
my @heads;
my $i=0;
while(my $r = $sth->fetchrow_arrayref()){
    $heads[$i]=$r->[0];
    $i++;
}
my $j=0;
foreach(@heads){
    print "$j $_\n";
    $j++;
}
$sth->finish();
$dbh->disconnect(); #disconnect from mysql db   
于 2022-01-26T00:43:55.527 回答