Plsql random numbers
| Fiche express | |
|---|---|
| Type | Package PL/SQL |
| Objet | Génération de nombres pseudo-aléatoires |
| Voir aussi | Plsql webdba utl pkg |
Plsql random numbers est un package PL/SQL implémentant un générateur de nombres pseudo-aléatoires par la méthode du générateur congruentiel linéaire (LCG). Il illustre une technique historique utile sur des versions d'Oracle anciennes ou dans des contextes où l'on veut un algorithme reproductible et auto-contenu, sans dépendance externe.
⚠️ Depuis longtemps, Oracle fournit le package standard DBMS_RANDOM (fonctions VALUE, NORMAL, STRING...), à préférer dans l'immense majorité des cas. Ce script garde un intérêt pédagogique (comprendre le principe d'un LCG) mais ne doit en aucun cas servir à générer des valeurs sensibles (mots de passe, jetons, sel de hachage) : un LCG est totalement prévisible dès que quelques valeurs de sortie sont connues, donc impropre à tout usage cryptographique.
Script
CREATE OR REPLACE PACKAGE random IS
-- Retourne un entier aléatoire dans [0, r-1]
FUNCTION rndint(r IN NUMBER) RETURN NUMBER;
-- Retourne un réel aléatoire dans [0, 1]
FUNCTION rndflt RETURN NUMBER;
END random;
/
CREATE OR REPLACE PACKAGE BODY random IS
m CONSTANT NUMBER := 100000000; -- conditions initiales
m1 CONSTANT NUMBER := 10000; -- (pour de meilleurs résultats)
b CONSTANT NUMBER := 31415821;
a NUMBER; -- graine (seed)
the_date DATE;
days NUMBER; -- pour générer la graine initiale
secs NUMBER;
-- Fonction utilitaire privée : multiplication modulaire évitant
-- le dépassement de précision NUMBER sur de grands produits
FUNCTION mult(p IN NUMBER, q IN NUMBER) RETURN NUMBER IS
p1 NUMBER;
p0 NUMBER;
q1 NUMBER;
q0 NUMBER;
BEGIN
p1 := TRUNC(p / m1);
p0 := MOD(p, m1);
q1 := TRUNC(q / m1);
q0 := MOD(q, m1);
RETURN (MOD((MOD(p0 * q1 + p1 * q0, m1) * m1 + p0 * q0), m));
END mult;
-- Retourne un entier aléatoire dans [0, r-1]
FUNCTION rndint(r IN NUMBER) RETURN NUMBER IS
BEGIN
-- Génère un nouveau nombre aléatoire et le fixe comme nouvelle graine
a := MOD(mult(a, b) + 1, m);
-- Le convertit en entier dans [0, r-1]
RETURN (TRUNC((TRUNC(a / m1) * r) / m1));
END rndint;
-- Retourne un réel aléatoire dans [0, 1]
FUNCTION rndflt RETURN NUMBER IS
BEGIN
a := MOD(mult(a, b) + 1, m);
RETURN (a / m);
END rndflt;
BEGIN
-- Initialise la graine "a" à partir de la date système
the_date := SYSDATE;
days := TO_NUMBER(TO_CHAR(the_date, 'J'));
secs := TO_NUMBER(TO_CHAR(the_date, 'SSSSS'));
a := days * 24 * 3600 + secs;
END random;
/
Utilisation
SELECT random.rndint(100) FROM dual; -- entier entre 0 et 99
SELECT random.rndflt FROM dual; -- réel entre 0 et 1
Voir aussi
- Plsql webdba utl pkg — autre exemple de package PL/SQL utilitaire (SQL dynamique)
- Drop db link — exemple de PL/SQL exécutant du DDL dynamique