dbms_random.string长度参数须为正整数,负数返回空字符串;value返回[0,1)浮点数,生成1–100整数应使用floor(value(1,101))。
dbms_random.string 生成随机字符时长度参数别传负数
传负数会返回空字符串,不是报错,容易误以为逻辑没生效。这个函数第二个参数是长度,正数才有效;负数(比如 -8)虽然语法合法,但 oracle 内部直接跳过生成逻辑。
常见错误现象:DBMS_RANDOM.STRING('A', -8) 返回 '',而你可能在拼接 SQL 或构造测试数据时发现字段突然为空。
-
'U':大写字母,'L':小写字母,'A':大小写混合,'X':字母+数字,'P':可打印 ASCII 字符(含标点) - 长度建议用正整数,比如
8、12,避免变量未校验就直接传入 - 如果需要固定前缀+随机后缀,别用
STRING拼接空格或特殊符号——它不生成空格,'P'也未必包含你想要的符号
DBMS_RANDOM.VALUE 生成随机数范围易被误解
DBMS_RANDOM.VALUE 返回的是 [0, 1) 区间浮点数,不是 [0, 1],更不是整数。想得到 1–100 的随机整数,不能直接 ROUND(DBMS_RANDOM.VALUE * 100),会轻微偏斜且可能出界。
正确做法是用 FLOOR + 偏移:
SELECT FLOOR(DBMS_RANDOM.VALUE(1, 101)) FROM DUAL;
说明:VALUE(low, high) 形参从 10g 开始支持,low 包含、high 不包含,所以 VALUE(1, 101) 才能稳定覆盖 1–100 整数。
- 旧版本(FLOOR(DBMS_RANDOM.VALUE * 100) + 1,但要注意
VALUE本身不带参数 - 别用
ROUND:0.5 会被上取整,100.0 出现概率略高,分布不均 - 性能上无显著差异,但语义清晰更重要——用双参数形式更直白,也少一层计算
DBMS_RANDOM.SEED 影响随机序列可重现性
调用 SEED 后,后续 STRING 或 VALUE 会按固定序列输出,这对测试有用,但上线后忘了重置就变成“伪随机”——每次连接都返回同一串。
典型场景:单元测试里设了 SEED(123),结果应用连接池复用 session,新请求拿到的还是种子 123 下的第 N 个值。
- 数值型 seed(如
123)和字符串型 seed(如'abc')行为一致,都是重置内部状态 - 生产环境一般别手动
SEED,除非明确需要可重现性;Oracle 默认用时间+进程号自动初始化 - 如果必须用 seed,建议每次会话只设一次,且避免用固定常量(比如写死
SEED(42))
DBMS_RANDOM 在 PL/SQL 函数里多次调用可能被优化掉
在 SQL 查询中内联调用 DBMS_RANDOM 是安全的,但在 PL/SQL 函数里,如果函数被标记为 DETERMINISTIC,Oracle 可能缓存结果,导致多次调用返回相同值。
错误示例:CREATE FUNCTION get_rand_str RETURN VARCHAR2 DETERMINISTIC IS BEGIN RETURN DBMS_RANDOM.STRING('X', 6); END; —— 这个函数在同一个查询里反复调用,很可能只算一次。
- 去掉
DETERMINISTIC关键字,这是最直接的解法 - 如果函数必须 deterministic(比如用于函数索引),那就不能依赖
DBMS_RANDOM,得换方案,比如用序列+映射表 - 注意:即使没标 deterministic,PL/SQL 中循环调用也要确认是否在同一个 execution context 下被意外复用
真正麻烦的不是怎么生成,而是生成之后没意识到它依赖 session 状态、seed 设置、或者被 PL/SQL 编译器悄悄优化了。










