2009-11-01 11 views
16

Poniższy kod wydaje się po prostu zbyt duży, aby uzyskać pojedynczą wartość zliczania. Czy istnieje lepszy, zalecany sposób pobierania pojedynczej wartości COUNT za pomocą zwykłego DBI?Jak mogę pobrać pojedynczą wartość licznika z bazy danych za pomocą 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; 
} 

To jest krótszy, ale nadal mam dwa oświadczenia.

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

To jest trochę subiektywne. Niektórzy powiedzieliby, że twój dłuższy przykład jest bardziej czytelny. Czy gramy w Perla Golfa? – pavium

+4

Czy ma znaczenie, ile masz wyciągów? –

+0

Mam wiele takich wywołań w moim kodu, więc mam sub, który pobiera instrukcji SQL i @params i zwraca liczbę. Gdybym miał wbudowane oświadczenie dla tego w DBI, to nie potrzebuję dodatkowego sub. Myślę, że jest to powszechny przypadek użycia i zastanawiałem się, czy jest takie stwierdzenie, a ja go nie zauważyłem lub nie ma takiego stwierdzenia w DBI. – szabgab

Odpowiedz

33

dość łatwe do zrobienia w jednej linii bez dodatkowych zmiennych :

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

To też byłoby moje rozwiązanie. – MarkR

+1

Tego właśnie szukałem. Dzięki! – szabgab

+0

Doktor powiedział, że powinieneś być w kontekście listy, osobiście używam '(mój $ count) = $ dbh-> selectrow_array ('SELECT count (*) FROM table WHERE ...', undef, @params);' –

3

Nie wiem, Perl, ale jeśli jest to składnia jest logiczne, że myślę, że to będzie działać w oparciu o 2 przykład:

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

Dobre przypuszczenie dla kogoś, kto nie zna Perla. :) – friedo

+0

ładne, choć powinno być $ dbh-> selectall_arrayref ("SELECT ...", undef, @params) -> [0] [0]; ponieważ wywołanie zwraca macierz, a nie wektor. (Miałem ten sam błąd w moim oryginalnym przykładzie, ale naprawiłem go od czasu twojego komentarza) – szabgab

+0

OK, naprawiłem to. –

1

pewnie nie byłoby to zrobić sam, ale zawsze można zrobić mu nową funkcję najwyższego poziomu obiektu DBH używasz:

OSTRZEŻENIE: nieprzetestowany kod następuje!

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; 

} 

a następnie nazwać tak:

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

Poza zanieczyszczających przestrzeń nazw, które nie jest twoje, ty też musisz napisać to dla każdego kierowcy DB użyć, choć jestem pewien swojej może coś wymyślić, co pozwoli ci na skonstruowanie i ewaluowanie kodu w celu automatycznej konfiguracji tego dla danego obiektu DBH.

+1

Oprócz zanieczyszczania cudzej przestrzeni nazw i konieczności przepisywania jej dla każdego używanego DBD, rozwiązanie przedstawione w formie wymaga interpolacji wartości w łańcuchu SQL zamiast tracić symbole zastępcze ("year_hired

+0

Dobra uwaga; Zastrzeżenie to było jednak odpowiedzią na komentarz PO "Gdybym miał do tego wbudowane oświadczenie w DBI". –

Powiązane problemy