Migliora significativamente le prestazioni (media delle decine di percento) su query che non possono essere risolte con una semplice ricerca di un singolo indice, ad es. join di tabelle. Tuttavia, ha il potenziale per nascondere dati/errore dell'applicazione.
Facciamo una tabella:
create table t (id number(10,0), padding varchar2(1000));
--intenzionalmente non usare PK per rendere l'esempio il più semplice possibile. Il riempimento viene utilizzato per simulare il carico di dati reale in ogni record
con molti record:
insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Ora se chiedi qualcosa come
select 1 into ll_exists
from t where id = 5;
il DB deve scorrere l'intera tabella se ha trovato l'unico record corrispondente nel primo blocco dati (che tra l'altro non possiamo sapere perché potrebbe essere inserito in molti modi diversi) o nell'ultimo. Questo perché non sa che esiste un solo record corrispondente. D'altra parte, se usi ... e rownum =1, può interrompere l'attraversamento dei dati dopo che il record è stato trovato perché gli hai detto che non c'è (o non è necessario) un altro record corrispondente.
Lo svantaggio è che con il vincolo rownum potresti ottenere risultati non deterministici se i dati contengono più di un possibile record. Se la query era
select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
quindi potrei ricevere dalla risposta DB 1 oltre a 3 e 123 ... l'ordine non è garantito e questa è la conseguenza. (senza la clausola rownum otterrei un'eccezione TOO_MANY_ROWS. Dipende dalla situazione qual è la peggiore)
Se vuoi davvero una query che verifica l'esistenza, SCRIVI IN QUEL MODO.
begin
select 'It does'
into ls_exists
from dual where
exists (your_original_query_without_rownum);
do_something_when_it_does_exist
exception
when no_data_found then
do_something_when_it_doesn't_exist
end;