前言

最近写了两个小脚本,一个应用于Mysql的自动填充测试数据,另外一个是bash写的定期删除日志文件,两个脚本如何使用,在GitHub上面都有所说明,这里不再赘述,这里主要是想聊一下Mysql的存储过程以及自动填充测试数据。

为什么要写一个自动填充测试数据的脚本?

网上其实也有一些简单的给Mysql填充数据的博客,但是大多数都是针对于特定的表的特定数据来实现,写的过于简单,实用性不强,而这个脚本可以根据我们提供表的字段,来自动识别我们的字段并填充进入对应的内容,常用的结构都能够满足,当然还有进一步完善的空间。

存储过程

Mysql的存储过程可以帮助我们实现一些较为复杂的业务逻辑,就像我们在PHP或者其他语言中所写的逻辑一样,在Mysql中也同样可以执行,比如我们要循环写入1000行数据。

不过虽然Mysql可以实现,但是我们更希望把业务逻辑建立在我们的业务语言上面,而Mysql则专注于处理数据的CURD,其主要原因在于我们今后在修改或者要查找到这块的业务逻辑时,会相对麻烦一些。

因此,我更倾向于Mysql可以用来做一些与我们的业务逻辑无关,而又需要用到语言的逻辑性的项目,比如我在前面提到的自动填充数据。

形式

delimiter $$

drop procedure if exists test $$

create procedure test()

begin

-- do something

end $$

delimiter ;

这是一个自动识别表结构并填充数据的脚本,在第一行使用了delimiter $$用作分隔符,因为接下来的脚本里面很多地方会使用到;,所以为防止过早的识别结束,暂时修改了Mysql默认的分隔符。

此外,前面有begin和end包裹,用于识别开始和结束。

暂时先不讲逻辑怎么实现的(其实逻辑也非常简单),我们先来了解一下Mysql的存储过程的几个部分。

注:通过show create procedure your_procedure_name可以查看创建的存储过程的代码内容。

变量

Mysql的变量分成三种:全局变量,用户变量,局部变量。

局部变量

局部变量存在于我们的存储过程中,在外面无法访问:

delimiter $$

drop procedure if exists test $$

create procedure test()

begin

declare myName varchar(8) default 'seven';

set myName = 'nine';

select myName;

end $$

delimiter ;

call test();

结果输出nine,因为在用户变量中需要@来声明,所以此时在外面无法使用select myName,否则报错。

用户变量

用户变量存在于全局,但是有效期仅限于会话期(所以也可以叫做会话变量),即我们下次打开Mysql时,变量就会消失:

delimiter $$

drop procedure if exists test $$

create procedure test()

begin

set @myName = 'nine';

end $$

delimiter ;

call test();

select @myName ;

输出nine。

当然,赋值的形式是多样的,我们也可以结合查询语句来赋值:

select name, age from user limit 1 into @myName , @myAge;

select @myName , @myAge;

这个时候赋值的内容就是我们表中的数据,这里需要注意的是一一对应关系,切不可一对多或者多对一。

在某些时候,我们可能需要对查询的次数进行记录,其实这个时候我们可以完全使用变量来帮我们实现:

set @selectNum = 0;

select * , @selectNum := @selectNum + 1 from user limit 1;

这个时候@selectNum的结果为2。

全局变量

全局变量是设置在系统中的配置,我们可以通过show global variables来查看,也可以通过set global oneofvariable=value来设置我们已经存在的配置,这里我特意给已经存在这几个字眼加粗,因为我在网上看到有博文说可以设置自定义的全局变量,但是我尝试了之后发现报错了,我用版本5.5和5.7都尝试过了,提示这个变量不存在。

参数

参数分成IN,OUT以及INOUT三种情况:

其实从其字面上我们也能猜出他们的不同效果:IN是不会影响外面设置的结果(IN是默认方式),OUT和INOUT是会影响到的,同时INOUT两边是相互影响的,我们还是以上面的test为例:

in

set @num = 1;

delimiter $$

drop procedure if exists test $$

create procedure test(num int)

begin

set num = 2;

end $$

delimiter ;

call test(@num);

select @num;

结果为1。

out

set @num = 1;

delimiter $$

drop procedure if exists test $$

create procedure test(OUT num int)

begin

set num = 2;

end $$

delimiter ;

call test(@num);

select @num;

结果为2。

语句块

这篇文章关于语句块已经阐述的足够详细,这里不再赘述。

实现

代码:

delimiter $$

drop procedure if exists fillTable $$

create procedure fillTable(in num int , in tbName varchar(16))

begin

-- 获取当前数据库

select (@dbName:=database());

set @tbName = tbName;

-- 获取表的字段总数

set @currSql = "select count(1) from information_schema.COLUMNS where table_name = ? and table_schema = ? into @columnSum";

prepare stmt from @currSql;

execute stmt using @tbName , @dbName;

deallocate prepare stmt;

set @currNum = 0;

-- 这里设置随机的字符串

set @chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

while @currNum < num do

-- 这里设置sql后面拼接

set @insertSql = concat("insert into " , @tbName , " values ( ");

set @columnNum = 1;

while @columnNum <= @columnSum do

set @value := '';

set @currSql = "select (@column := COLUMN_NAME) , (@length := CHARACTER_MAXIMUM_LENGTH) , (@key := COLUMN_KEY) , (@type := DATA_TYPE) from information_schema.COLUMNS where table_name = ? and table_schema = ? limit ?";

prepare stmt from @currSql;

execute stmt using @tbName , @dbName , @columnNum;

deallocate prepare stmt;

-- 根据类型来填充数据

if right(@type , 3) = 'int' then

if @type = 'int' then

set @value = 'default';

else

set @value = floor(rand() * 100);

end if;

elseif right(@type , 4) = 'char' then

set @counter = 0;

while @counter < @length do

set @value = concat(@value,substr(@chars,ceil(rand()*(length(@chars)-1)),1));

set @counter = @counter + 1;

end while;

set @value = concat("'" , @value , "'");

elseif @type = 'blob' or right(@type , 4) = 'text' then

set @counter = 0;

while @counter < 100 do

set @value = concat(@value,substr(@chars,ceil(rand()*(length(@chars)-1)),1));

set @counter = @counter + 1;

end while;

set @value = concat("'" , @value , "'");

elseif @type = 'float' or @type = 'decimal' then

set @value = round(rand() , 2);

else

set @value = 'nine';

end if;

-- 判断这个数是否是最后一个

if @columnNum = @columnSum then

set @insertSql = concat(@insertSql , @value , ' )');

else

set @insertSql = concat(@insertSql , @value , ' , ');

end if;

set @columnNum = @columnNum + 1;

end while;

-- 执行

prepare stmt from @insertSql;

execute stmt;

deallocate prepare stmt;

set @currNum = @currNum + 1;

end while;

end $$

delimiter ;

其实实现这个功能的逻辑非常简单,再各个步骤里面也附上了步骤,主要是利用了系统的information_schema.COLUMNS表来获取我们需要的一些基本信息,主要结构如下图所示:

参考

mysql自动填充_Mysql自动填充测试数据相关推荐

  1. mysql自动编号_MySQL自动编号与主键

    1.自动编号(AUTO_INCREMENT),必须与主键组合使用 默认情况下,起始值为1,增量也为1. 2.主键(PRIMARY KEY) 每张数据表只能存在一个主键 主键保证记录的唯一性 主键自动为 ...

  2. 取消mysql自动备份文件_MySQL自动备份并清理多少天前的备份文件

    自动备份一.利用mysql提供的mysqldump工具进行数据库的导入导出二.使用shell命令执行mysqldump/usr/local/mysql/bin/mysqldump --opt -uba ...

  3. mysql 手工修复_MySQL自动备份和手工恢复

    欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 以下是windows下的批处理: 1set hour_str=%time:~0,2% 2if "%hour_st ...

  4. mysql生成序列_mysql 自动生成编号函数

    根据需求,保存表数据时需要自动生成一个编号,格式如:AA-2020-03-31-0001  (AA-yyyy-MM-dd-序号).数据库用的mysql,所以创建一个mysql函数. 1.建表: cre ...

  5. mysql的自动编码_mysql 自动生成编号函数

    根据需求,保存表数据时需要自动生成一个编号,格式如:AA-2020-03-31-0001  (AA-yyyy-MM-dd-序号).数据库用的mysql,所以创建一个mysql函数. 1.建表: cre ...

  6. mysql重连_mysql自动重连

    最近部署一个系统,后台用线程池来处理请求,而每个线程有一个mysql连接.当系统运行一阶段后,有些请求会出现操作"Internal error",而操作一次可能又会成功.经过多方调 ...

  7. mysql 备份 发送邮件_mysql 自动备份发邮件 到指定邮箱

    首先 编写 导出的 命令 使用了 mysqladmin ping mysqldump 然后是 添加附件到邮件中发送 使用了对应的com 最后 暂停 看情况 参考: 见程序: @echo on :: m ...

  8. mysql自动排序_mysql自动排序

    最近在写一个项目,在项目中有一个要求是按照指定的用户指定顺序,对数据进行排序!网上百度了一下,感觉还是挺有用的,但是不是很清楚工作原理! mysql的field()函数 filed(s,s1,s2.. ...

  9. mysql保存测试数据_Mysql自动填充测试数据

    前言 最近写了两个小脚本,一个应用于Mysql的自动填充测试数据,另外一个是bash写的定期删除日志文件,两个脚本如何使用,在GitHub上面都有所说明,这里不再赘述,这里主要是想聊一下Mysql的存 ...

最新文章

  1. Java之Array(数组)说明
  2. 成都理工大学乐千桤java考试_2009年度优秀教师、优秀教务工作者评选结果公示-成都理工大学工会...
  3. RGB565与RGB555位图文件格式的标志识别
  4. 【LOJ】#2887. 「APIO2015」雅加达的摩天楼 Jakarta Skyscrapers
  5. [置顶]       spring + jstl 实现java国际化的配置步骤
  6. JAVA学习:maven开发环境快速搭建
  7. Java 11 升级:“债务”“危机”
  8. 凝思系统改时间_大众改原厂盲点监测系统,中山大众原厂改装,途观L改盲点监测...
  9. 没有配置默认路由_网络路由选择原理
  10. HDU - 2602 01背包
  11. javaweb实现学生管理系统
  12. vue 文件转base64方法 base64转blob路径方法 a链接下载文件 form表单下载文件
  13. VTuber拍摄幕后:操作员、动捕设备、软件支撑
  14. 递归的本质(栈:后进先出)
  15. 人工智能在计算机领域的应用论文,人工智能应用领域论文 关于人工智能领域的大学论文...
  16. 杂文-61儿童节-太阳的距离
  17. 【Nodejs】使用request批量下载MP3,文件数量内容都没问题
  18. 底部的footer导航栏被手机虚拟键盘顶起来如何解决
  19. 超低延时的H5直播,电子游戏互动控制直播,桌面远程控制直播方案
  20. Office系列办公软件中的一款-Microsoft Excel提供下载

热门文章

  1. java怎么使两个界面联系_怎么样用java编写界面实现两个数的加法运算
  2. [******] 树问题:普通二叉树的创建与遍历
  3. linux swap 分区调控(swap分区 lvm管理)
  4. 面向对象的编程-类和实例
  5. Java之Exception
  6. Centos7下zabbix部署(四)定义报警媒介-邮件
  7. 判断浏览器 插件 jquery.ua.js
  8. android的ListView做表格添加圆角边框
  9. 用C#实现MD5算法
  10. 53 - leetcode 1. 两数之和 数据结构map类