Det forbedrer ydeevnen betydeligt (tivis af procent gennemsnit) på forespørgsler, som ikke kan løses ved simpelt enkelt indeksopslag, f.eks. tabel joins. Det har dog et potentiale til at skjule data/applikationsfejl.
Lad os få et bord:
create table t (id number(10,0), padding varchar2(1000));
--Brug ikke PK med vilje for at gøre eksemplet så enkelt som muligt. Polstringen bruges til at simulere reel databelastning i hver post
med mange optegnelser:
insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Hvis du nu spørger noget som
select 1 into ll_exists
from t where id = 5;
DB'en skal gennemgå hele tabellen, om den fandt den eneste matchende post i den første datablok (som vi i øvrigt ikke kan vide, fordi den kunne indsættes på mange forskellige måder) eller i den sidste. Det er fordi den ikke ved, at der kun er én matchende rekord. På den anden side, hvis du bruger ... og rownum =1, kan den stoppe med at krydse data, efter at posten er fundet, fordi du fortalte den, at der ikke er (eller ikke nødvendig) en anden matchende post.
Ulempen er, at med rownum-begrænsningen kan du få udeterministiske resultater, hvis dataene indeholder mere end én mulig post. Hvis forespørgslen var
select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
så får jeg måske fra DB svar 1 samt 3 samt 123 ... rækkefølge er ikke garanteret og det er konsekvensen. (uden rownum-sætningen ville jeg få en TOO_MANY_ROWS undtagelse. Det afhænger af situationen, hvilken der er værst)
Hvis du virkelig ønsker at forespørge, hvilken test eksistens, så SKRIV DET SÅDAN.
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;