上一篇介绍了如何在 Oracle 生成随机数字、字符串、日期、验证码以及 UUID,今天我们继续讨论在 MySQL 中生成各种随机数据的方法。
📝计算机生成的都是伪随机数,并不是真正的物理随机数。
生成随机数字
生成 0 到 1 之间的随机数
MySQL 中的 RAND 函数可以用于生成一个大于等于 0 小于 1 的随机数字。例如:
SELECT rand();
rand() |
------------------|
0.7245639057127423|
SELECT rand();
rand() |
-------------------|
0.01697599982561171|
该函数返回的数据类型为 double,包含 16 位小数;每次调用都会返回不同的数据。
如果想要重现某些场景,需要确保每次运行时生成相同的随机数。这种情况下可以为 RAND 函数传递一个输入参数,设置一个随机数种子。例如:
SELECT rand(1);
rand(1) |
-------------------|
0.40540353712197724|
SELECT rand(1);
rand(1) |
-------------------|
0.40540353712197724|
从结果可以看出,相同的种子返回了相同的随机数。
生成指定范围内的随机数
基于 RAND 函数和数学运算,可以返回任意两个数字之间的随机数:
low + RAND() * (high − low)
以上表达式将会返回一个大于等于 low,小于 high 的随机数。例如:
SELECT 10 + rand(1) * 10;
10 + rand(1) * 10 |
------------------|
14.054035371219772|
以上示例返回了一个大于等于 10 且小于 20 的随机数字。
如果想要生成某个范围内的随机整数,可以加上 FLOOR 函数。例如:
SELECT floor(10 + rand(1) * (10)) AS rd;
rd |
----|
14.0|
该语句返回了一个大于等于 10,小于等于 19(不是 20)的随机整数。
生成 6 位数字手机验证码
我们已经获得了指定范围内的随机整数,加上 LPAD 函数就可以生成由 6 位数字字符组成的手机验证码。例如:
SELECT lpad(floor(rand(999) * 1000000), 6, '0') AS captcha;
captcha|
-------|
088146 |
其中,lpad 函数可以确保数据不够 6 位时在前面补足 0。
生成遵循正态分布的随机数
RAND 函数生成的是一个遵循均匀分布的随机数,MySQL 没有提供生成遵循正态分布(normal distribution)的随机数。我们可以创建一个存储函数来模拟正态分布的随机数:
delimiter //
create function normal_distrib(mean double, stdev double)
returns double no sql
begin
set @x = rand(), @y = rand();
set @nd = (sqrt(-2 * log(@x)) * cos(2 * pi() * @y)) * stdev + mean;
return @nd;
end
//
delimiter ;
以上函数利用 Box-Muller 变换算法通过两个平均分布的随机数生成正态分布的随机数。
以下语句通过 normal_distrib 函数生成了一个期望值为 0,标准差为 1 的正态分布随机数:
SELECT normal_distrib(0,1);
normal_distrib(0,1)|
-------------------|
1.4930564399841173|
以下语句可以用于验证 normal_distrib 函数是否遵循正态分布:
with recursive temp(val) as (
select normal_distrib(0,1)
union all
select normal_distrib(0,1)
from temp
limit 1000000
)
select /*+ set_var(cte_max_recursion_depth = 1m) */avg(val),std(val)
from temp;
avg(val) |std(val) |
---------------------|------------------|
-0.002340136192616743|0.9994844557755181|
通过运行 1000000 次,计算这些数据的平均值和标准差,返回结果非常接近 0 和 1。
生成随机字符串
生成固定长度的随机字符串
除了随机数字之外,有时候我们也需要生成一些随机的字符串。MySQL 没有提供专门生成随机字符串的函数,但是可以通过其他函数进行模拟。例如:
SELECT char(floor(rand() * 26)+65) as rand_char;
rand_char|
---------|
T |
以上查询返回了一个随机的大写字母,char 函数用于将 ASCII 码转换为对应的字符。我们可以基于该查询进一步创建一个存储函数:
delimiter //
create function rand_string(len integer)
returns text no sql
begin
declare counter int default 1;
declare str text default '';
if len < 1 then
return null;
end if;
while counter <= len do
set str = concat(str, char(floor(rand() * 94) + 33));
set counter = counter + 1;
end while;
return str;
end
//
delimiter ;
rand_string 函数可以返回由仺UTN8#УjX[>K5yIZ8ZzK.8iz^i8XNyNikk9^yNih~z[K{NZIyX[45yIZUTNXh^Z{J.zKK^XNih~zhn{~{XyNyX[>ih~z[ZJ~Z^YZIiJ |