使用Perl获取所有记录DBI
我有一个使用DBI连接的Perl脚本。我打开并使用子例程读取SQL脚本文件。我打印的只有一条记录,我应该有两条记录(共三条记录)。我如何获得所有记录?使用Perl获取所有记录DBI
结果:
Alert:OUTBOUND_DATA:0
脚本:
my $dbh_oracle = DBI->connect(
$CFG{oracle_dbi_connect},
$CFG{db_user},
$CFG{db_cred},
{AutoCommit => 0,
RaiseError => 0,
PrintError => 0}) or die ("Cannot connect to the database: ".$DBI::errstr."\n");
my ($val1, $val2) = get_data();
print "Alert:$val1:$val2\n";
send_email("Alert:$val1:$val2");
sub get_data
{
undef $/;
open (my $QFH, "< /sql/summary.sql") or die "error can't open this file $!";
my $sth= $dbh_oracle->prepare(<$QFH>) or
die ("Cannot connect to the database: ".$DBI::errstr."\n");
$sth->execute;
close $QFH;
my $row = $sth->fetchrow_hashref;
$sth->finish;
return @$row{'MYTABLE','FLAG'};
}
sub send_email {
my $message = shift;
open (MAIL, "|/usr/sbin/sendmail -t") or die "Can't open sendmail: $!";
print MAIL "To: me\@test.com\n";
print MAIL "From: Data\n";
print MAIL "\n";
print MAIL $message;
close MAIL;
}
exit;
从运行的查询结果:(超过1个REC)
MYTABLE FLAG
----------------------- ----------
OUTBOUND_DATA 0
MSGS_BY_DIM 0
INBOUND_DATA 0
3 rows selected.
这也取决于你如何构建你的整体脚本。您的get_data()
调用只允许返回一对值。我看到至少有几个选项:或者返回一个包含所有数据的散列(引用),然后让main
进行汇编,或者使用前面提到的循环结构,并在子例程内部构造消息体,只返回一个标量字符串。
返回所有数据作为一个哈希参考,get_data
子程序可能是这样的(请注意我用的fetchall_hashref
代替fetchrow_hashref
:
sub get_data
{
undef $/;
open (my $QFH, "< /sql/summary.sql") or die "error can't open this file $!";
my $sth= $dbh_oracle->prepare(<$QFH>) or
die ("Cannot connect to the database: ".$DBI::errstr."\n");
$sth->execute;
close $QFH;
my $hash_ref = $sth->fetchall_hashref('MYTABLE');
$sth->finish;
return $hash_ref;
}
你从main
调用它,并使用输出如下:
my $hash_ref = get_data();
my $message = "";
foreach my $table (sort keys %$hash_ref) {
$message .= join(":", "Alert", $table, $$hash_ref{$table}{'FLAG'}) . "\n";
}
这将导致含有$message
:
Alert:INBOUND_DATA:0
Alert:MSGS_BY_DIM:0
Alert:OUTBOUND_DATA:0
而且你可能要礼貌地问:
$dbh_oracle->disconnect;
你之前退出。
这有一些问题,例如你已经将SQL存储在一个外部脚本中,但是我已经使用硬编码密钥(MYTABLE,我认为它在您的查询中是唯一的)和值FLAG),当您想要扩展时,这将在稍后限制。
这就是我一直在寻找的。我试图建立在使用子程序。感谢您提供'main'示例作为汇编所有输出的方式。 – cjd143SD 2012-04-21 02:50:13
该线路应该是一个循环:
my $row = $sth->fetchrow_hashref;
它应该是:
my @rows;
while (my $row = $sth->fetchrow_hashref) {
push @rows, $row;
}
return @rows;
如果你宁愿有DBI为你做的回路中,检查出selectall_arrayref或selectall_hashref
有,你可以从一个语句句柄检索数据许多不同的方式。最常见的是相当简单,如下所示它们的用途:
my @row_array = $sth->fetchrow_array;
my $array_ref = $sth->fetchrow_arrayref;
my $hash_ref = $sth->fetchrow_hashref;
第一,fetchrow_array,将依次为阵列返回的每一行。如上所述使用来自选择返回的数据的一个例子可以是:
while (my @row_array = $sth->fetchrow_array) {
print $row_array[0], " is ", $row_array[1], " years old, and has a " ,
$row_array[2], "\n";
}
第二个例子是类似的,但返回的数组引用,而不是一个数组:
while (my $array_ref = $sth->fetchrow_arrayref) {
print $array_ref->[0], " is ", $array_ref->[1],
" years old, and has a " , $array_ref->[2], "\n";
}
第三个例子,fetchrow_hashref,往往是最具可读性:
while (my $hash_ref = $sth->fetchrow_hashref) {
print $hash_ref->{name}, " is ", $hash_ref->{age},
" years old, and has a " , $hash_ref->{pet}, "\n";
}
fetchrow_
方法实际上只是一次取一行。
如果您想要某些列的所有行,则可能无效率地推送数据结构或使用适合您情况的调用。
在我看来,要使用selectcol_arrayref
为:
my $ary_ref = $dbh->selectcol_arrayref(
"select id, name from table",
{ Columns=>[1,2] }
);
列索引引用列的位置在结果集中,而不是原来的表。
您使用返回结果的方式也需要更改以处理所有返回的行。
此外,你必须:
sub get_data
{
undef $/;
因为你啜包含SQL文件。但是,$/
是一个全局变量。你应该在尽可能小的范围内使用local $/
。所以:
my $sql = do { local $/; <$fh> };
是的,我同意在这些情况下,我希望查询中的所有内容看起来像'selectcol_arrayref'将是您的选择。你对使用'local $ /'的建议,我会把它作为一个子程序还是将它留在外面?谢谢。 – cjd143SD 2012-04-21 01:35:15
您可以设置'RAISEERROR => 1',且无需为那些死()调用。 – pilcrow 2012-04-21 00:21:03
另外,我注意到你已经禁用了'RaiseError'和'PrintError'。第一个错误是致命的,第二个错误至少会打印出来(但不会杀死你的代码)。您应该至少将其中的一个设置为真实值,以免您的错误被丢弃。 – Ovid 2012-05-04 13:32:35