Il améliore considérablement les performances (moyenne de dizaines de pour cent) sur les requêtes qui ne peuvent pas être résolues par une simple recherche d'index unique, par ex. jointures de table. Cependant, il est possible de masquer les erreurs de données/d'application.
Faisons un tableau :
create table t (id number(10,0), padding varchar2(1000));
-- intentionnellement, n'utilisez pas PK pour rendre l'exemple aussi simple que possible. Le rembourrage est utilisé pour simuler le chargement réel des données dans chaque enregistrement
avec de nombreux enregistrements :
insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Maintenant, si vous demandez quelque chose comme
select 1 into ll_exists
from t where id = 5;
la base de données doit parcourir toute la table si elle a trouvé le seul enregistrement correspondant dans le premier bloc de données (ce que nous ne pouvons d'ailleurs pas savoir car il peut être inséré de différentes manières) ou dans le dernier. C'est parce qu'il ne sait pas qu'il n'y a qu'un seul enregistrement correspondant. D'un autre côté, si vous utilisez ... et rownum =1, il peut arrêter de parcourir les données une fois l'enregistrement trouvé car vous lui avez dit qu'il n'y a pas (ou pas besoin) d'autre enregistrement correspondant.
L'inconvénient est qu'avec la contrainte rownum, vous pouvez obtenir des résultats indéterministes si les données contiennent plus d'un enregistrement possible. Si la requête était
select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
alors je peux recevoir de la DB la réponse 1 ainsi que 3 ainsi que 123... la commande n'est pas garantie et c'est la conséquence. (sans la clause rownum, j'obtiendrais une exception TOO_MANY_ROWS. Cela dépend de la situation, laquelle est la pire)
Si vous voulez vraiment une requête qui teste l'existence, ÉCRIVEZ-LA DE CETTE FAÇON.
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;