2012-01-18 12 views
6

Con DBI esiste un modo per determinare se un handle di istruzione eseguita per un'istruzione SELECT restituirà qualsiasi riga senza recuperare da esso?

I.e. qualcosa di simile:

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

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

e voglio eseguire il test $sth will return at least one rowsenza eseguire qualsiasi metodo fetch su $sth.

Nota - non ho bisogno il conteggio esatto delle righe (vale a dire $sth->rows), ho solo bisogno di sapere se $sth->rows sarà> 0.

risposta

8

$ sth-> file è ancora la scelta migliore. Come hai detto, controlla se è superiore a 0.

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

TRANNE! la documentazione DBI dice che questo non è affidabile per selezionare le statistiche fino a quando tutte le righe sono state recuperate. Non esiste un modo per determinare quante righe verranno recuperate in anticipo. Se avete bisogno di sapere questo il consiglio è di fare prima un

select count(*) from <table> 

Vedi this section of the DBI documentation.

+0

Potrebbe non funzionare a seconda del driver, ad esempio con DBD :: Oracle, $ sth-> rows restituisce il numero di righe interessate solo per aggiornamenti, eliminazioni e inserimenti ma -1 per selects (http://search.cpan.org/~pythian/DBD-Oracle-1.74/lib/DBD/Oracle.pm# righe) – Fred

1

Invece di cercare qualcosa in DBI, è possibile utilizzare SQL per questo. Basta avvolgere SELEZIONA in un altro SELECT con ESISTE condizione:

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

Non è SQL portatile: FROM DUAL potrebbe essere diversa sul vostro RDBMS, vostro DB potrebbe non supportare esiste e subquery. Tuttavia, i DB più moderni ti consentono di cucinare qualcosa di simile.

Dovrebbe essere il modo più efficace in cui l'ottimizzatore può ignorare l'ordine ignorato, per raggruppare, i limiti della query secondaria. Controlla i piani di esecuzione.

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

È anche possibile, ma il DB deve controllare l'intero set di dati per ottenere il numero corretto di righe.

Se si controlla il builder SQL, è possibile eliminare l'ordine per, gruppo per (solo se non si ha anche parte) e applicare il limite per selezionare solo una riga.

0

Forse questo è quello che stai cercando.

"attivo" (boolean, di sola lettura)

L'attributo "attivo" è vero se l'oggetto maniglia è "attivo". Questo è raramente utilizzato nelle applicazioni. Il significato esatto di attivo è alquanto vago al momento. Per un database gestirlo in genere significa che l'handle è connesso a un database ("$ dbh-> disconnect" imposta "Active" su off). Affinché una dichiarazione venga gestita, in genere significa che l'handle è un "SELECT" che potrebbe avere più dati da recuperare. (Il recupero di tutti i dati o la chiamata "$ sth-> finish" disattiva "Attivo")

+0

No. Come si cita nella risposta, 'Attivo' di solito significa che un comando di istruzione * potrebbe * avere più righe da recuperare. Quindi, anche una dichiarazione eseguita che sappiamo * a priori * non restituirà ancora alcuna riga (con driver tipici come 'DBD :: mysql') riporta 'Active' finché non viene chiamato il primo (e finale)' fetch() '. – pilcrow

2

Non credo che esista un modo affidabile per verificare se è possibile recuperare qualsiasi riga diversa dal recupero. Ovviamente una volta che hai recuperato la prima riga, non è disponibile per essere recuperata e devi tenerla "in mano". Ma questo non è troppo difficile da affrontare.

Io in genere pensare di utilizzare idiomi come una delle seguenti due:

... 
$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 
} 

o

... 
$sth->execute; 

my @rows; 

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

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

O semplicemente usare '$ sth-> fetchall_arrayref()' direttamente come descritto in https://stackoverflow.com/a/47679059/111036 se i risultati attesi sarebbero di dimensioni ragionevoli. – mivk

Problemi correlati