2009-11-01 8 views
16

Le code suivant semble être trop, pour obtenir une seule valeur de comptage. Existe-t-il une meilleure façon recommandée d'extraire une seule valeur COUNT en utilisant DBI simple?Comment puis-je récupérer une seule valeur de comptage à partir d'une base de données avec DBI?

sub get_count { 
    my $sth = $dbh->prepare("SELECT COUNT(*) FROM table WHERE..."); 
    $sth->execute(@params); 
    my $($count) = $sth->fetchrow_array; 
    $sth->finish; 

    return $count; 
} 

Ceci est plus court, mais j'ai toujours deux instructions.

sub get_count_2 { 
    my $ar = $dbh->selectall_arrayref("SELECT ...", undef, @params) 
    return $ar->[0][0]; 
} 
+1

C'est un peu subjectif. Certains diront que votre exemple plus long est plus lisible. Jouons-nous au Perl Golf? – pavium

+4

Est-ce que le nombre de déclarations importe? –

+0

J'ai beaucoup d'appels de ce type dans mon code, donc j'ai un sous qui obtient l'instruction SQL et le @params et renvoie le nombre. Si j'avais une instruction intégrée pour DBI, je n'ai pas besoin du sous-marin supplémentaire. Je pense que c'est un cas d'usage courant et je me demandais s'il y avait une telle déclaration et si je l'avais manquée ou s'il n'y avait pas une telle déclaration dans DBI. – szabgab

Répondre

33

assez facile à faire dans une ligne sans variables supplémentaires :

$count = $dbh->selectrow_array('SELECT count(*) FROM table WHERE...', undef, @params); 
+1

Ce serait aussi ma solution. – MarkR

+1

C'est ce que je cherchais. Merci! – szabgab

+0

Le doc a dit que vous devriez être dans un contexte de liste, personnellement j'utilise '(my $ count) = $ dbh-> selectrow_array ('SELECT count (*) FROM table WHERE ...', undef, @params);' –

3

Je ne sais pas Perl, mais si elle est la syntaxe est logique je pense que cela fonctionnerait en fonction de votre 2ème exemple:

sub get_count { 
    return $dbh->selectall_arrayref("SELECT ...", undef, @params)->[0][0]; 
} 
+2

Bonne estimation pour quelqu'un qui ne connaît pas Perl. :) – friedo

+0

sympa, bien que cela devrait être $ dbh-> selectall_arrayref ("SELECT ...", undef, @params) -> [0] [0]; comme l'appel renvoie une matrice et non un vecteur. (J'ai eu la même erreur dans mon exemple original mais je l'ai corrigé depuis votre commentaire) – szabgab

+0

OK, corrigé. –

1

Je ne serais probablement pas faire moi-même, mais vous pouvez toujours faire une nouvelle fonction de haut niveau de l'objet DBH que vous utilisez:

ATTENTION: le code non testé suit!

sub DBD::SQLite::db::count 
{ 
    my($dbh, $table, $where) = @_; 

    my($stmt) = "SELECT COUNT(*) FROM $table"; 
    $stmt .= " WHERE $where" if $where; 

    my($count) = $dbh->selectrow_array($stmt); 

    return $count; 

} 

puis l'appeler comme ceci:

my($cnt) = $dbh->count('Employee', 'year_hired < 2000'); 

Outre la pollution d'un espace de noms qui ne vous appartient pas, vous auriez aussi écrire ceci pour chaque pilote DB que vous utilisez, mais je suis sûr que votre pourrait fonctionner quelque chose qui vous permet de construire et d'évaluer du code pour le configurer automatiquement pour un objet DBH donné.

+1

En plus de polluer l'espace de nom de quelqu'un d'autre et de devoir le réécrire pour chaque DBD que vous utilisez, la solution telle que présentée vous oblige à interpoler les valeurs dans la chaîne SQL au lieu de perdre des espaces réservés ('year_hired

+0

Bon point; Cependant, c'était en réponse au commentaire de l'OP «Si j'avais une déclaration intégrée pour cela dans DBI». –