Ele melhora significativamente o desempenho (dezenas de porcentagem média) em consultas que não podem ser resolvidas por simples pesquisa de índice único, por exemplo A tabela une. No entanto, tem o potencial de ocultar erros de dados/aplicativos.
Vamos a uma tabela:
create table t (id number(10,0), padding varchar2(1000));
--intencionalmente não use PK para tornar o exemplo o mais simples possível. O preenchimento é usado para simular a carga de dados real em cada registro
com muitos registros:
insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Agora, se você perguntar algo como
select 1 into ll_exists
from t where id = 5;
o banco de dados deve percorrer toda a tabela se encontrou o único registro correspondente no primeiro bloco de dados (o que, aliás, não podemos saber porque poderia ser inserido de muitas maneiras diferentes) ou no último. Isso porque ele não sabe que existe apenas um registro correspondente. Por outro lado, se você usar ... e rownum =1, ele pode parar de percorrer os dados após o registro ser encontrado porque você disse que não há (ou não é necessário) outro registro correspondente.
A desvantagem é que com a restrição rownum você pode obter resultados não determinísticos se os dados contiverem mais de um registro possível.
select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
então eu posso receber do DB resposta 1, bem como 3, bem como 123 ... a ordem não é garantida e essa é a consequência. (sem a cláusula rownum eu receberia uma exceção TOO_MANY_ROWS. Depende da situação qual é a pior)
Se você realmente deseja consultar o que testa a existência, ESCREVA ASSIM.
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;