Comment éviter que le programme se ferme lorsque DBI de Perl rencontre une erreur lors de la préparation d'une instruction?

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

  •  08-07-2019
  •  | 
  •  

Question

Je crée un script qui parcourt une table contenant tous les autres noms de table de la base de données. En analysant chaque ligne, il vérifie si la table est vide par

select count(*) cnt from $table_name 

Certaines tables n'existent plus dans le schéma et si je le fais

select count(*) 

directement dans l'invite de commande, il renvoie l'erreur:

  

206: la table spécifiée (adm_rpt_rec) n'est pas dans la base de données.

Lorsque je le lance à partir de Perl, il ajoute ceci au début:

  

Echec de la préparation de DBD :: Informix :: db: SQL: -

Comment éviter que le programme ne se ferme lorsqu'il essaie de préparer cette instruction SQL?

Était-ce utile?

La solution

Code de travail - en supposant que vous disposiez d'une base de données "magasins".

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

Résultat de l'exécution du code ci-dessus.

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.

Ceci imprimait l'erreur ( PrintError = > 1 ), mais continuait. Changez le 1 en 0 et aucune erreur ne s’affiche. Les parenthèses dans les déclarations de $ tabname et $ num sont cruciales - contexte de tableau vs contexte scalaire.

Autres conseils

Une option consiste à ne pas utiliser RaiseError = > 1 lors de la construction de $ dbh. L’autre consiste à envelopper la préparation dans un bloc eval.

Il suffit de mettre les appels qui peuvent échouer dans un bloc eval comme ceci:

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

Bien que, dans ce cas, puisque vous utilisez Informix, vous avez une bien meilleure option: les tables de catalogue système. Informix conserve les métadonnées comme celles-ci dans un ensemble de tables de catalogue système. Dans ce cas, vous voulez 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";
} 

Ceci est plus rapide et plus sûr que décompte (*) du tableau. La documentation complète des tables de catalogue système se trouve dans IBM Informix Guide to SQL (il s’agit d’un document PDF).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top