我有一个使用DBI连接的Perl脚本。我使用子例程打开并读取SQL脚本文件。我只打印一条记录,我应该再打印两条记录(总共三条记录)。我如何获得所有记录?
结果:
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.
答案 0 :(得分:8)
有许多不同的方法可以从语句句柄中检索数据。最常见的是非常简单,它们的使用如下所示:
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";
}
答案 1 :(得分:3)
这一行应该是一个循环:
my $row = $sth->fetchrow_hashref;
应该是:
my @rows;
while ( my $row = $sth->fetchrow_hashref ) {
push @rows, $row;
}
return @rows;
如果你想让DBI为你做循环,请查看selectall_arrayref或selectall_hashref
答案 2 :(得分:2)
这还取决于您如何构建整个脚本。您的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) )在脚本中,当你想要扩展它时,这将限制。
答案 3 :(得分:2)
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> };