2009-11-01 7 views
16

El siguiente código parece ser demasiado para obtener un único valor de recuento. ¿Existe una forma mejor y recomendada de obtener un único valor de COUNT con DBI simple?¿Cómo puedo obtener un valor de recuento único de una base de datos con 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; 
} 

Esto es más corto, pero todavía tengo dos declaraciones.

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

Esto es un poco subjetivo. Algunos dirían que su ejemplo más largo es más legible. ¿Estamos jugando Perl Golf? – pavium

+4

¿Importa cuántas declaraciones tiene? –

+0

Tengo muchas de esas llamadas en mi código, así que tengo un sub que obtiene la instrucción SQL y los parámetros y devuelve el recuento. Si tuviera una declaración incorporada para eso en DBI, entonces no necesito el submarino adicional. Creo que es un caso de uso común y me preguntaba si hubo tal afirmación y me la perdí o si no hay tal declaración en DBI. – szabgab

Respuesta

33

bastante fácil de hacer en una sola línea sin variables adicionales :

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

Esa sería mi solución también. – MarkR

+1

Eso es lo que estaba buscando. ¡Gracias! – szabgab

+0

El doc dijo que deberías estar en el contexto de la lista, personalmente uso '(my $ count) = $ dbh-> selectrow_array ('SELECT count (*) FROM table WHERE ...', undef, @params);' –

3

No sé Perl, pero si es la sintaxis es lógico yo creo que esto funcionaría en base a su segundo ejemplo:

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

Buena conjetura para alguien que no conoce a Perl. :) – friedo

+0

nice, aunque debería ser $ dbh-> selectall_arrayref ("SELECT ...", undef, @params) -> [0] [0]; como la llamada devuelve una matriz y no un vector. (Tuve el mismo error en mi ejemplo original pero lo arreglé desde su comentario) – szabgab

+0

OK, solucionado eso. –

1

que probablemente no haría esto a mí mismo, pero siempre se podía hacer una nueva función de nivel superior del objeto DAP que está utilizando:

ADVERTENCIA: ¡sigue el código no probado!

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; 

} 

y luego llamarlo así:

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

además de contaminar un espacio de nombres que no es el suyo, también tendría que escribir esto para todos los pilotos DB utiliza, aunque estoy seguro de que su podría funcionar algo que le permita construir y evaluar algún código para configurarlo automáticamente para un objeto DBH dado.

+1

Además de contaminar el espacio de nombres de otra persona y la necesidad de reescribirlo para cada DBD que utilice, la solución tal como se presenta requiere que interpole los valores en la cadena SQL en lugar de perder marcadores de posición ('year_hired

+0

Buen punto; Sin embargo, el motivo de esto fue en respuesta al comentario de la OP "si tuviera una declaración incorporada para eso en DBI". –

Cuestiones relacionadas