当Perl的DBI在准备语句时遇到错误时,如何避免程序退出?

时间:2009-05-07 20:20:11

标签: sql perl informix dbi

我正在创建一个脚本,该脚本通过一个包含数据库中所有其他表名的表。在解析每一行时,它会通过

检查表是否为空
select count(*) cnt from $table_name 

架构中不存在某些表格,如果我这样做了

select count(*) 

直接进入命令提示符,它返回错误:

  

206:指定的表(adm_rpt_rec)不在数据库中。

当我从Perl中运行它时,它会将其添加到开头:

  

DBD :: Informix :: db prepare failed:SQL: -

如何在尝试准备此SQL语句时避免程序退出?

3 个答案:

答案 0 :(得分:3)

一个选项是不使用RaiseError => 1构造$ dbh时。另一种是将准备包装在一个eval块中。

答案 1 :(得分:3)

只需将可能失败的调用放在eval块中,如下所示:

for my $table (@tables) {
    my $count;
    eval {
        ($count) = $dbi->selectrow_array("select count(*) from $table");
        1; #this is here so the block returns true if it succeeds
    } or do {
        warn $@;
        next;
    }
    print "$table has $count rows\n";
}

虽然在这种情况下,由于您使用的是Informix,因此您有一个更好的选择:系统目录表。 Informix将这样的元数据保存在一组系统目录表中。在这种情况下,您需要systables:

my $sth = $dbh->prepare("select nrows from systables where tabname = ?");
for my $table (@tables) {
    $sth->execute($table);
    my ($count) = $sth->fetchrow_array;
    $sth->finish;
    unless (defined $count) {
        print "$table does not exist\n";
        next;
    }
    print "$table has $count rows\n";
} 

这比表格count(*)更快,更安全。可以在IBM Informix Guide to SQL中找到系统目录表的完整文档(警告这是PDF)。

答案 2 :(得分:2)

工作代码 - 假设您有一个'商店'数据库。

#!/bin/perl -w
use strict;
use DBI;
my $dbh = DBI->connect('dbi:Informix:stores','','',
                       {RaiseError=>0,PrintError=>1}) or die;
$dbh->do("create temp table tlist(tname varchar(128) not null) with no log");
$dbh->do("insert into tlist values('systables')");
$dbh->do("insert into tlist values('syzygy')");

my $sth = $dbh->prepare("select tname from tlist");
$sth->execute;
while (my($tabname) =  $sth->fetchrow_array)
{
    my $sql = "select count(*) cnt from $tabname";
    my $st2 = $dbh->prepare($sql);
    if ($st2)
    {
        $st2->execute;
        if (my($num) = $st2->fetchrow_array)
        {
            print "$tabname: $num\n";
        }
        else
        {
            print "$tabname: error - missing?\n";
        }
    }
}
$sth->finish;
$dbh->disconnect;
print "Done - finished under control.\n";

运行上面代码的输出。

systables: 72
DBD::Informix::db prepare failed: SQL: -206: The specified table (syzygy) is not in the database.
ISAM: -111: ISAM error:  no record found. at xx.pl line 14.
Done - finished under control.

这打印了错误(PrintError=>1),但仍在继续。将1更改为0,不会出现错误。 $tabname$num声明中的括号是至关重要的 - 数组上下文与标量上下文。