Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.misc -> Re: Random selection of records in PL/SQL
doid wrote:
> > HShukla538 wrote: > > > > How can i select a true random record in pl/sql >
I've done this in the past using code like:
foo:=random.next_int(range)+offset;
select * into rec
from bar
where key>foo
and rownum=1;
(ie I have a numeric key in the table, I generate a random number based on the offset and range of the values of this key (offset=min(key), range=max(key)-min(key)).)
The random number generator I used varied; in one case I was doing this in perl, so I used its random number generator to help build the sql; in other cases I've used a random number generator I converted from one in Numerical Recipes in C (Oxford University Press). The generator was a linear congruential generator with shuffling and had a pretty long period, so was random enough for almost any purpose.
The code is included below - use it at your own risk. It's not as efficient as it could be, but I didn't want to spend much time on it, other than to get a working conversion.
Hope this helps. Brian =========================================BEGINset verify off
create or replace package random is
--PRIVATE UTILITIES function get_persistent(id varchar2) return number; procedure set_persistent(id varchar2, value number);end random;
if j<NTAB then set_persistent(to_char(j),idum1); end if; end loop; set_persistent('iy',get_persistent('0')); set_persistent('idum1',idum1); end seed; function next_num return number is idum1 number; idum2 number; iy number; temp number; k number; j integer; begin -- restore the persisted values idum1:=get_persistent('idum1'); idum2:=get_persistent('idum2'); iy:=get_persistent('iy'); --generator1 begins here. --uses Schrager's method for calculating --mod without overflow. Not really necessary --here; number's are much bigger than 32 bit. k:=floor(idum1/IQ1); idum1:=IA1*(idum1-k*IQ1)-k*IR1; if idum1<0 then idum1:=idum1+IM1; end if; -- second generator. k:=floor(idum2/IQ2); idum2:=IA2*(idum2-k*IQ2)-k*IR2; if idum2<0 then idum2:=idum2+IM2; end if; -- shuffle/combine generators j:=floor(iy/NDIV); iy:=get_persistent(to_char(j))-idum2; if (iy<1) then iy:=iy+IMM1; end if; -- before returning, set the new persistents... set_persistent(to_char(j),idum1); set_persistent('idum1',idum1); set_persistent('idum2',idum2); set_persistent('iy',iy); --prevent endpoints being returned temp := AM*iy; if temp>RNMX then temp:=RNMX; end if; return temp; end next_num;
-- maintain persistent storage
function get_persistent(id varchar2) return number is retval number; begin select value into retval from random_persist where id=get_persistent.id; return retval; end get_persistent; procedure set_persistent(id varchar2,value number) is small_string random_persist.id%type; begin small_string:=substr(id,1,length(small_string)); insert into random_persist (id,value) select small_string, set_persistent.value from dual where not exists ( select null from random_persist where id=small_string ); update random_persist set value=set_persistent.value where id=set_persistent.id; end set_persistent;
-- convenience function to return integers up to a specified
range. function next_int(max_int integer) return integer is begin return floor(next_num*max_int); end next_int;
-- return the random number as a base 26 number, with digits
-- as letters in the range a-z. This prevents the user seeing
-- both the internal representation and the full precision of
the
-- number, to increase security. 32-bit randoms will return
-- trailing 'AAA...' strings for more than about 10 chars.
function next_string(chars in integer) return varchar2 is next_letter integer; i integer; temp number; retval varchar2(32); begin retval:=''; temp:=next_num; for i in 1 .. chars loop next_letter:=floor(temp*26); temp:=(temp*26)-next_letter; retval:=concat(retval,CHR(next_letter+ASCII('a'))); end loop; return retval; end next_string;
-- ****====---- Brian Ewins. Fax: (44) 141 220 6100 Tel: (44) 141 220 6121 "It's time we face reality, my friends... We're not exactly rocket scientists." --Gary Larson ----====****Received on Wed Jun 11 1997 - 00:00:00 CDT