2012-01-18 10 views
6

Z czy istnieje sposób na określenie, czy wykonywany uchwyt instrukcji dla instrukcji SELECT zwróci wiersze bez pobierania z niego?

tj. coś takiego:

use DBI; 
... 
my $sth = $dbh->prepare("SELECT ..."); 
$sth->execute; 

if (..$sth will return at least one row...) { 
    ... 
} else { 
    ... 
} 

i chcę przeprowadzić test $sth will return at least one rowbez prowadzącym jakąkolwiek metodę pobierania na $sth.

Uwaga - Nie potrzebuję dokładną liczbę wierszy (tj $sth->rows), tylko trzeba wiedzieć, czy będzie $sth->rows> 0.

Odpowiedz

8

$ sth-> wierszy jest nadal najlepszym rozwiązaniem. Jak już powiedziałeś, sprawdź, czy jest to więcej niż 0.

if ($sth->rows > 0){ 
    # magic here! 
} 

Z WYJĄTKIEM! Dokumentacja DBI mówi, że nie jest ona wiarygodna dla wybranych pozycji, dopóki wszystkie wiersze nie zostaną pobrane. Nie ma sposobu, aby określić, ile wierszy zostanie pobranych z góry. Jeśli chcesz wiedzieć to rada jest, aby najpierw zrobić

select count(*) from <table> 

Zobacz this section of the DBI documentation.

+0

może nie działać w zależności od kierowcy, na przykład z DBD :: Oracle, $ sth-> rows zwraca liczbę wierszy, których dotyczy tylko aktualizacja, usuwa i wstawia, ale -1 dla zaznaczeń (http://search.cpan.org/~pythian/DBD-Oracle-1.74/lib/DBD/Oracle.pm# wiersze) – Fred

1

Zamiast szukać czegoś w DBI, możesz użyć SQL do tego. Wystarczy owinąć SELECT do innego SELECT z EXISTS warunek:

SELECT 1 FROM DUAL WHERE EXISTS (SELECT ...); 

To nie jest przenośny SQL: FROM DUAL mogą wyglądać inaczej na różnych RDBMS, Twój DB nie może wspierać istnieje i podzapytania. Jednak większość nowoczesnych DB pozwala ci gotować coś takiego.

Powinien być najbardziej skuteczny, ponieważ optymalizator może pominąć zignorowanie zamówienia według, grupy według, limitów w podrzędnym zapytaniu. Sprawdź plany wykonania.

SELECT COUNT(*) FROM (SELECT ...) 

Jest również możliwe, ale DB musi sprawdzić cały zestaw danych, aby uzyskać prawidłową liczbę wierszy.

Jeśli kontrolujesz program budujący SQL, możesz zrzucić zamówienie według, grupy według (tylko, jeśli nie ma części również) i nałożyć limit, aby wybrać tylko jeden wiersz.

0

Może tego właśnie szukasz.

"Active" (logiczna, tylko do odczytu)

"Aktywne" atrybut jest prawdziwe, jeśli obiekt uchwyt jest "aktywny". Jest to rzadko używane w aplikacjach. Dokładne znaczenie aktywnego jest w tej chwili niejasne. W przypadku obsługi bazy danych zwykle oznacza, że ​​uchwyt jest podłączony do bazy danych ("$ dbh-> disconnect" ustawia "Active" off). W przypadku instrukcji obsługi zwykle oznacza to, że uchwyt jest "SELECT", który może mieć więcej danych do pobrania. (Pobieranie wszystkich danych lub wywołanie „$ sth-> Zakończ” ustawia „Aktywny” off).

+0

Nie. Jak cytujesz w swojej odpowiedzi, 'Aktywny' zwykle oznacza, że ​​uchwyt instrukcji * może * mieć więcej wierszy do pobrania. Tak więc nawet wykonana instrukcja, którą znamy * a priori * zwróci żadne wiersze, jeszcze nie będzie (pod typowymi sterownikami jak 'DBD :: mysql') zgłasza' Active' dopóki nie zostanie wywołany pierwszy (i ostatni) 'fetch()'. – pilcrow

2

Nie sądzę, istnieje jakikolwiek wiarygodny sposób testowania czy jakieś wiersze mogą zostać pobrane inne niż ich pobierania. Oczywiście, gdy już pobierzesz pierwszy wiersz, nie będzie on dostępny do pobrania i musisz trzymać go w ręku. Ale nie jest to zbyt trudne.

bym generalnie myślę używać idiomów jak jeden z następujących dwóch kryteriów:

... 
$sth->execute; 

my @rows; 

my $row = $sth->fetchrow_hashref(); 

if ($row) { 
    do { 
     # do something with $row 
     ... 

     $row = $sth->fetchrow_hashref(); 
    } while ($row); 
} else { 
    # No rows 
} 

lub

... 
$sth->execute; 

my @rows; 

while (my $row = $sth->fetchrow_hashref()) { push @rows, $row } 

if (@rows) { 
    # Some rows, now in @rows 
} else { 
    # No rows 
} 
+0

Lub po prostu użyj '$ sth-> fetchall_arrayref()' bezpośrednio jak opisano w https://stackoverflow.com/a/47679059/111036, jeśli oczekiwane wyniki będą miały rozsądny rozmiar. – mivk

Powiązane problemy