Como posso evitar que o programa parar quando DBI do Perl encontra um erro preparar uma declaração?

StackOverflow https://stackoverflow.com/questions/836827

  •  08-07-2019
  •  | 
  •  

Pergunta

Eu estou fazendo um script que passa por uma tabela que contém todos os outros nomes de tabelas no banco de dados. Como ele analisa cada linha, ele verifica para ver se a tabela está vazia por

select count(*) cnt from $table_name 

Algumas tabelas não existe no esquema mais e se eu fizer isso

select count(*) 

diretamente no prompt de comando, ele retorna o erro:

206:. A tabela especificada (adm_rpt_rec) não está no banco de dados

Quando eu executá-lo a partir de dentro Perl, ele acrescenta o seguinte no início:

DBD :: Informix :: db preparar falhou: SQL: -

Como posso evitar que o programa parar quando ele tenta preparar esta instrução SQL?

Foi útil?

Solução

Código de Trabalho -. Supondo que você tenha um banco de dados 'lojas'

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

Saída da execução do código acima.

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.

Este impresso o erro (PrintError=>1), mas continuou. Alterar o 1 a 0 e não aparece erro. Os parênteses nas declarações de $tabname e $num são cruciais - contexto gama vs contexto escalar

.

Outras dicas

Uma opção não é para uso RaiseError => 1 ao construir $ dbh. O outro é para embrulhar a preparar em um bloco de eval.

Apenas colocar as chamadas que podem falhar em um bloco de eval como esta:

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

Embora, neste caso, uma vez que você estiver usando Informix, você tem uma opção muito melhor: as tabelas de catálogo do sistema. Informix mantém metadados como este em um conjunto de tabelas de catálogo do sistema. Neste caso, você quer 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";
} 

Esta é mais rápido e mais seguro do que count(*) contra a mesa. A documentação completa das tabelas de catálogo do sistema pode ser encontrado em IBM Informix Guide to SQL (aviso este é um PDF).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top