在这里使用bind_col 不会为您带来任何好处。正如您已经知道的那样,它用于将固定数量的结果绑定到一组变量。但是你没有固定的集合。
考虑哦,我可以动态地创建它们是一个很常见的错误。它会给你into all kinds of trouble later。 Perl 有一个专门针对这个用例的数据结构:散列。
DBI 内置了一堆函数,用于在execute 之后检索数据。其中之一是fetchrow_hashref。它将结果作为哈希引用返回,每列一个键,一次一行。
while (my $res = $sth->fetchrow_hashref) {
p $res; # p is from Data::Printer
}
假设结果如下所示:
$res = {
id => 1,
color => 'red',
}
您可以通过说$res->{color} 来访问颜色。 perlref 和 perlreftut 上的 perldocs 有很多关于此的信息。
请注意,命名语句句柄变量的最佳做法是$sth。
在您的情况下,您有动态数量的列。这些必须以col1, col2, col3 的格式加入。我猜你已经在$colsf 中做到了。 $tab 中的表格非常明显,所以我们只剩下 $whr 了。
这部分很棘手。这对always sanitize your input 很重要,尤其是在 CGI 环境中。对于 DBI,最好使用 placeholders 来完成。他们会为您处理所有的转义,并且易于使用。
my $sth = $dbi->prepare('select cars from garage where color=?');
$sth->execute($color);
现在我们不需要关心颜色是red、blue 还是' and 1; --,它们可能有损坏的东西。如果这一切都非常动态,请改用$dbi->quote。
让我们把它放在你的代码中。
use strict;
use warnings;
use DBI;
# ...
# the columns
my $colsf = join ',', @some_list_of_column_names; # also check those!
# the table name
my $table = $q->param('table');
die 'invalid table name' if $table =~ /[^a-zA-Z0-9_]/; # input checking
# where
# I'm skipping this part as I don't know where it is comming from
if ($op eq 'SELECT') {
my $sql = 'SELECT $colsf FROM $table';
$sql .= ' WHERE $whr' if $whr;
my $sth = $dbh->prepare($sql) or die $dbi->errstr;
$sth->execute;
my @headings = $sth->{NAME}; # see https://metacpan.org/pod/DBI#NAME1
while (my $res = $sth->fetchrow_hashref) {
# do stuff here
}
}