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

发布于 2024-07-19 07:40:33 字数 430 浏览 12 评论 0原文

我正在制作一个脚本来遍历包含数据库上所有其他表名称的表。 当它解析每一行时,它会检查表是否为空,

select count(*) cnt from $table_name 

某些表在架构中不再存在,如果我

select count(*) 

直接在命令提示符中执行此操作,它会返回错误:

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

当我从 Perl 内部运行它时,它会将其附加到开头:

DBD::Informix::db 准备失败:SQL:-

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

I'm making a script that goes through a table that contains all the other table names on the database. As it parses each row, it checks to see if the table is empty by

select count(*) cnt from $table_name 

Some tables don't exist in the schema anymore and if I do that

select count(*) 

directly into the command prompt, it returns the error:

206: The specified table (adm_rpt_rec) is not in the database.

When I run it from inside Perl, it appends this to the beginning:

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

How can I avoid the program quitting when it tries to prepare this SQL statement?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

是你 2024-07-26 07:40:33

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

One option is not to use RaiseError => 1 when constructing $dbh. The other is to wrap the prepare in an eval block.

阳光的暖冬 2024-07-26 07:40:33

只需将可能失败的调用放在 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 SQL 指南(警告这是 PDF)。

Just put the calls that may fail in an eval block like this:

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";
}

Although, in this case, since you are using Informix, you have a much better option: the system catalog tables. Informix keeps metadata like this in a set of system catalog tables. In this case you want 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";
} 

This is faster and safer than count(*) against the table. Full documentation of the system catalog tables can be found in IBM Informix Guide to SQL (warning this is a PDF).

并安 2024-07-26 07:40:33

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

#!/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 声明中的括号至关重要 - 数组上下文与标量上下文。

Working code - assuming you have a 'stores' database.

#!/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";

Output from running the code above.

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.

This printed the error (PrintError=>1), but continued. Change the 1 to 0 and no error appears. The parentheses in the declarations of $tabname and $num are crucial - array context vs scalar context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文