Comment puis-je savoir combien de lignes une requête Perl DBI retourne?

j'essaie de faire une recherche dans la base de données avec Perl pour savoir s'il y a un élément avec un certain ID. Cette recherche ne peut pas retourner de lignes, mais elle peut aussi en renvoyer une.

j'ai le code suivant:

my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0] != $exid) {
        ...

fondamentalement, cela essaie de voir si L'ID a été retourné et si ce n'est pas le cas, continuez avec le script. Mais il envoie une erreur de référence de tableau Null Sur le $th->fetch()->[0] chose. Comment puis-je simplement vérifier si elle a retourné des lignes ou maintenant?

18
demandé sur brian d foy 2009-01-14 00:08:53

7 réponses

my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
my $found = 0;
while ($th->fetch()) 
{
   $found = 1;
}

votre requête ne retournera rien si la ligne n'existe pas, donc vous ne pouvez pas dé-référencer le fetch.

mise à Jour: vous pouvez ré-écrire que sous la forme

my $found = $th->fetch();
13
répondu Paul Tomblin 2014-08-05 22:54:28

DBD:: mysql pilote a un rows() méthode qui permet de retourner le nombre de résultats:

$sth = $dbh->prepare( ... );
$sth->execute;
$rows = $sth->rows;

ceci est spécifique aux pilotes de base de données, donc il se peut que cela ne fonctionne pas avec d'autres pilotes, ou que cela fonctionne différemment avec d'autres pilotes.

31
répondu brian d foy 2012-04-05 02:09:43

pourquoi ne pas simplement "sélectionner count (*)..."??

my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = '$exid'");

Ou de contrecarrer Peu De Bobby Tables:

my $q_exid = $dbh->quote($exid);
my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = $q_exid");

Ou si vous allez exécuter beaucoup cela:

my $sth = $dbh->prepare("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = ?");
....save $sth (or use prepare_cached()) and then later
my ($got_id) = $dbh->selectrow_array($sth, undef, $exid);
4
répondu runrig 2009-01-13 23:45:48

modifier sélectionner pour toujours retourner quelque chose? Cela devrait fonctionner à Sybase, Je ne sais pas à propos d'autres DBs.

my $th = $dbh->prepare(qq{SELECT count(*) FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0]) {
....
}
3
répondu Arkadiy 2009-01-13 21:24:26

en général, je ne sais pas pourquoi les gens ont si peur des exceptions. Vous les attraper et de les déplacer sur.

my $sth = prepare ...
$sth->execute;
my $result = eval { $sth->fetchrow_arrayref->[1] };

if($result){ say "OH HAI. YOU HAVE A RESULT." }
else       { say "0 row(s) returned."         }

dans ce cas, cependant, la réponse de Paul est la meilleure.

Également $sth->rows ne fonctionne généralement pas jusqu'à ce que vous avez récupéré chaque ligne. Si vous voulez savoir combien de lignes correspondent, alors vous devez réellement demander au moteur de base de données la question que vous voulez connaître la réponse à; à savoir select count(1) from foo where bar='baz'.

2
répondu jrockway 2009-01-13 21:59:21

Le seul moyen fiable pour découvrir le nombre de lignes renvoyées par une requête SELECT est de récupérer tous les compter. Comme indiqué dans le DBI documentation:

généralement, vous ne pouvez compter que sur une rangée Compter après une non-SELECT execute (for certaines opérations spécifiques comme UPDATE et supprimer), ou après avoir récupéré tous les les lignes d'une instruction SELECT.

pour sélectionner les déclarations, il n'est généralement pas possible de savoir combien de lignes seront retournés, sauf par les parcourir toutes. Certains pilotes retourneront le nombre de lignes l'application a été récupérée ainsi loin, mais d'autres peuvent revenir -1 jusqu'à toutes les rangées ont été récupérées. Afin que l'utilisation de la méthode rows ou $DBI:: rows avec SÉLECTIONNEZ consolidés n'est pas recommandé.

Toutefois, lorsque vous descendez à elle, vous presque jamais besoin de savoir à l'avance, de toute façon. Juste une boucle sur while ($sth->fetch) pour traiter chaque ligne ou, pour le cas particulier d'une requête qui ne retournera que zéro ou une ligne,

if ($sth->fetch) {
  # do stuff for one row returned
} else {
  # do stuff for no rows returned
}
1
répondu Dave Sherohman 2009-01-13 22:37:10

cet article peut aider les utilisateurs MySQL:

http://www.arraystudio.com/as-workshop/mysql-get-total-number-of-rows-when-using-limit.html

heureusement depuis MySQL 4.0.0 vous pouvez utiliser L'option SQL_CALC_FOUND_ROWS dans votre requête qui va dire à MySQL de compter le nombre total de lignes sans tenir compte de la clause LIMIT. Vous avez encore besoin pour exécuter une deuxième requête pour récupérer le nombre de lignes, mais c'est une requête simple et pas aussi complexe que votre requête extrait les données.

L'Usage est assez simple. Dans votre requête principale, vous devez ajouter L'option SQL_CALC_FOUND_ROWS juste après SELECT et dans la seconde requête vous devez utiliser la fonction FOUND_ROWS() pour obtenir le nombre total de lignes. Les requêtes ressembleraient à ceci:

SELECT SQL_CALC_FOUND_ROWS name, email FROM users WHERE name LIKE 'a%' LIMIT 10;

SELECT FOUND_ROWS ();

La seule limitation est que vous devez appeler deuxième requête immédiatement après la première parce que SQL_CALC_FOUND_ROWS n'enregistre pas le nombre de lignes nulle part.

bien que cette solution nécessite également deux requêtes, elle est beaucoup plus rapide, puisque vous n'exécutez la requête principale qu'une seule fois.

vous pouvez en savoir plus sur SQL_CALC_FOUND_ROWS et FOUND_ROWS() dans MySQL docs.

1
répondu LeeGee 2012-11-07 10:33:04