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
중요한 - 배열 컨텍스트 대 스칼라 컨텍스트입니다.
다른 팁
하나의 옵션은 $ dbh를 구성 할 때 RaidError => 1을 사용하지 않는 것입니다. 다른 하나는 준비 블록에 준비를 감싸는 것입니다.
다음과 같은 평가 블록에 실패 할 수있는 통화 만 넣으십시오.
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는 시스템 카탈로그 테이블 세트에서 이와 같은 메타 데이터를 유지합니다. 이 경우 시스템을 원합니다.
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(*)
테이블에. 시스템 카탈로그 테이블의 전체 문서화는 SQL에 대한 IBM Informix 안내서 (경고 PDF입니다).