赞
踩
来自上一篇文章Python 生成批量随机密码的启发,生成批量随机密码是否可以再Mysql上实现呢?经研究答案是可以的,因此本文将使用Mysql简单查询和储存过程给大家进一步实现生成批量随机密码。
首先我们先熟悉下Mysql中存在的字符集,使用char()查看哪一些字符是可以用于生成密码的;
# 查看Mysql的字符集有哪些
with recursive cte (n) as
(
select 1
union all
select n + 1 from cte where n < 200
)
select n,char(n) t
from cte;
-- 48:57 0-9
-- 65:90 A-Z
-- 97:122 a-z
-- 33:126 数字、英文字母、特殊字符
描述:这个查询语句使用了递归和char()函数,查看1-200对应的字符有哪些,由于行记录太多在这里不做显示,可以前往数据库操作查看,通过查看可知 48:57对应0-9数字、65:90对应A-Z大写英文字母、97:122对应a-z小写英文字母、33:126对应数字、英文字母、特殊字符;
利用随机函数rand()和向下取整函数floor()选取步骤1中需要的字符对应的整数;
select char(floor(rand() * 9)+48) a -- 随机生成48:57对应0-9数字
union all
select char(floor(rand() * 89)+33) a -- 随机生成33:126对应数字、英文字母、特殊字符
;
然后我们可以巧妙的利用递归和group_concat()根据需要的长度进行拼接成字符串;
with recursive cte1(n1) as
(select 1
union all
select n1 + 1 from cte1 where n1 < 10), -- 递归出需要生成的用户id长度的10条记录
cte2(n2) as
(select 1
union all
select n2 + 1 from cte2 where n2 < 30) -- 递归出需要生成的密码长度的30条记录
select group_concat(char(floor(rand() * 9)+48) separator '') t
from cte1 -- 生成长度为10的用户id
union all
select group_concat(char(floor(rand() * 89)+33) separator '') t
from cte2 -- 生成长度为30的用户密码
;
在这里,我们定义三个常见易变的变量,根据步骤2的测试结果,进一步利用笛卡尔积将用户id和密码进行合并;
-- 定义用户长度、密码长度和生成的总数量三个变量 set @user_length = 10; set @password_length = 30; set @total_num = 10; with recursive cte1(n1) as (select 1 union all select n1 + 1 from cte1 where n1 < @user_length), -- 递归出需要生成的用户id长度数量记录 cte2(n2) as (select 1 union all select n2 + 1 from cte2 where n2 < @password_length), -- 递归出需要生成的密码长度数量记录 cte3(n3) as (select 1 union all select n3 + 1 from cte3 where n3 < @total_num), -- 递归出需要生成的总数量记录 user_id as (select n3, group_concat(char(floor(rand() * 9) + 48) separator '') user_id from cte3 join cte1 group by n3), -- 根据总数量记录与用户id长度记录做笛卡尔积,再根据总数量汇总拼接每个数量对应的用户id长度字符组 password as (select n3, group_concat(char(floor(rand() * 89) + 33) separator '') password from cte3 join cte2 group by n3) -- 根据总数量记录与密码长度记录做笛卡尔积,再根据总数量汇总拼接每个数量对应的密码长度字符组 select n3, user_id, password from user_id join password using (n3) ;
描述:这里是通过简单的查询实现,可以定义和修改三个变量,重新执行进行复用,也用使用存储过程进一步实现;
创建有用户长度、密码长度和总数量三个参数的存储过程;
create procedure generate_random_passwords(in user_length int,in password_length int,in total_num int) begin set @user_set := (with recursive cte (n) as (select 48 union all select n + 1 from cte where n < 57) select group_concat(char(n) separator '') a from cte); -- 定义用户id字符集 set @password_set := (with recursive cte (n) as (select 33 union all select n + 1 from cte where n < 126) select group_concat(char(n) separator '') a from cte); -- 定义密码字符集 set @num := 1; set @sql := ''; -- 创建一个临时表用于存储用户id和密码信息 create temporary table if not exists temp_passwords ( id int auto_increment primary key, user_id varchar(255) comment '用户id', `password` varchar(255) comment '密码' ); -- 使用while循环产出一定量的用户id和密码 while @num <= total_num do set @user_id := ''; set @password := ''; -- 根据给定的用户id长度,循环产出对应数量的用户id while char_length(@user_id) <= user_length do set @user_id := concat(@user_id, substring(@user_set, floor(1 + rand() * char_length(@user_set)), 1)); end while; -- 根据给定的密码长度,循环产出对应数量的密码 while char_length(@password) <= password_length do set @password := concat(@password, substring(@password_set, floor(1 + rand() * char_length(@password_set)), 1)); end while; -- 将生成的用户id和密码录入到临时表 insert into temp_passwords(user_id,`password`) values (@user_id,@password); -- 循环满足截止条件 set @num := @num + 1; end while; -- 查询查看结果 select user_id,`password` from temp_passwords; -- 清空临时表 truncate table temp_passwords; end; call generate_random_passwords(10,30,10)
描述:这里用到了存储过程和循环的知识,实现的整体思路还是和步骤2差不多一致。调用generate_random_passwords()存储过程输入要的三个参数就可得到所需要的密码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。