PerlのDBIでステートメントの準備中にエラーが発生したときにプログラムが終了しないようにするにはどうすればよいですか?
質問
データベース上の他のすべてのテーブル名を含むテーブルを通過するスクリプトを作成しています。各行を解析する際、
によってテーブルが空かどうかを確認しますselect count(*) cnt from $table_name
一部のテーブルはスキーマにもう存在しないため、その場合は
select count(*)
コマンドプロンプトに直接入力すると、エラーが返されます:
206:指定されたテーブル(adm_rpt_rec)はデータベースにありません。
Perl内から実行すると、これが先頭に追加されます。
DBD :: Informix :: db準備に失敗しました:SQL:-
このSQLステートメントを準備しようとしたときにプログラムが終了しないようにするにはどうすればよいですか?
解決
作業コード-「ストア」データベースがあると仮定します。
#!/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
の宣言の括弧は重要です-配列コンテキストとスカラーコンテキスト。
他のヒント
1つのオプションは、RaiseError =&gtを使用しないことです。 $ dbhを構築する場合は1。もう1つは、準備を評価ブロックでラップすることです。
次のように、失敗する可能性のある呼び出しを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であるという警告)。