Database   Information
Information Random Numbers.

Loads of times (well twice) I've been asked if PL/SQL has a random number function and I always answer "Erm, I dunno. Have you looked in the manuals?". Bit of a crap answer I know, but there you go.

I think Oracle® are more or less justified in not giving us a random number generator 'cos it's not really a 'relational' thing to want to do. So, just to piss them off, here's the PL/SQL code for a pseudo-random number generating package based on the standard C library code, which itself is based on the BASIC random number algorithm (I think).

This is your package header, create it first. D'oh.
   
  CREATE OR REPLACE PACKAGE random AS
--
   --
   -- Seeds the generator with the given value
   PROCEDURE seed(p_value IN NUMBER);
   PRAGMA RESTRICT_REFERENCES(seed,WNDS,RNDS);
   --
   -- Returns a random decimal between 0 and 1 (inclusive)
   FUNCTION fraction RETURN NUMBER;
   PRAGMA RESTRICT_REFERENCES(fraction,WNDS,RNDS);
   --
   -- Returns an integer between p_from and p_to (inclusive)
   FUNCTION value(p_from IN NUMBER,p_to IN NUMBER) RETURN NUMBER;
   PRAGMA RESTRICT_REFERENCES(value,WNDS,RNDS);
--
END random;
/
 
     

This is the actual code. You might want to create grants, synonyms and all that jazz.
   
  CREATE OR REPLACE PACKAGE BODY random AS
--
   --
   -- A package global to store the current random number
   g_random NUMBER := 1;
--
   --
   -- Seeds the generator with the given value
   PROCEDURE seed(p_value IN NUMBER) IS
   BEGIN
     g_random := ROUND(p_value);
   EXCEPTION
     WHEN OTHERS THEN g_random := 32767;
   END seed;
--
   --
   -- Returns a random decimal between 0 and 1 (inclusive)
   FUNCTION fraction RETURN NUMBER IS
   BEGIN
     BEGIN
       g_random := ((g_random * 214013) + 2531011)/65536;
       g_random := MOD(g_random,32768);
     EXCEPTION
       WHEN OTHERS THEN g_random := 32767;
     END;
     RETURN g_random/32767;
   END fraction;
--
   --
   -- Returns an integer between p_from and p_to (inclusive)
   FUNCTION value(p_from IN NUMBER,p_to IN NUMBER) RETURN NUMBER IS
     l_from NUMBER := LEAST(p_from,p_to);
     l_to NUMBER := GREATEST(p_from,p_to);
   BEGIN
     RETURN ROUND((fraction * ((l_to - l_from) + 0.95)) + (l_from - 0.5));
   END value;
--
END random;
/
 
     

Just like all (most?) computer based random number generators, this will actually return a pre-defined sequence of numbers, as long as it's always seeded with the same value. This can be useful in some circumstances when you need 'predictable randomness', if there is such a thing. To get closer to actual randomness you should seed the generator with a random(ish) number. I usually find the current time's a good 'un. Something like 'ROUND((((hour*3600)+(minute*60)+second)/86400)*10000)' might be a good starting point. Or you could use something based on 'MOD(dbms_utility.get_time,32768)' but that doesn't guarantee not to update the database so then you wouldn't be able to use it in SQL statements (like you'd want to?). Oh well, if I was kind I'd have put something like that into the package for you, but I'm not. So you'll have to do it yourself.

Sorry.
 




G.E.M