Mysql自动填充测试数据
前言
最近写了两个小脚本,一个应用于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.1 表设计 create_time默认值添加CURRENT_TIMESTAMP. update_time默认值添加CURRENT_TIMESTAMP,更新打勾. 1.2 验证是否成 ...
- Mysql自动设置时间(自动获取时间,填充时间)
应用场景: 1.在数据表中,要记录每条数据是什么时候创建的,不需要应用程序去特意记录,而由数据数据库获取当前时间自动记录创建时间: 2.在数据库中,要记录每条数据是什么时候修改的,不需要应用程序去特意 ...
- ThinkPHP 自动验证与自动填充无效可能的原因(转)
自动验证与自动填充是在使用ThinkPHP时经常用到的功能,但偶尔会遇到自动验证与自动填充无效的情况,本文就ThinkPHP 自动验证与自动填充无效可能的原因做一些分析. create() Think ...
- 【mybatis-plus】主键id生成、字段自动填充
一.主键id的生成 数据库表里通常都会有一个主键id,来作为这条数据的唯一标识. 常见的方式 数据库自动增长 这种很常见了,可以做到全库唯一.因为id是天然排序的,对于涉及到排序的操作会很方便. UU ...
- Mybatis plus通用字段自动填充的最佳实践总结
在进行持久层数据维护(新增或修改)的时候,我们通常需要记录一些非业务字段,比如:create_time.update_time.update_by.create_by等用来维护数据记录的创建时间.修改 ...
- 项目集成seata和mybatis-plus冲突问题解决方案:(分页插件失效, 自动填充失效, 自己注入的id生成器失效 找不到mapper文件解决方案)
项目集成seata和mybatis-plus,seata与mybatis-plus冲突问题(所有插件失效,自动填充失效,找不到mapper文件解决方案) 自动填充代码: package com.fro ...
- chrome防止自动填充密码
是防止,不是禁止.禁止需要在浏览器设置. chrome浏览器保存密码之后,页面上有password存在的时候会出现自动填充用户名和密码的情况. 添加disableautocomplete和autoco ...
- combobox实现模糊查询自动填充
利用winform设计软件界面时,经常用到combobox控件,但有时需要绑定数据表中的数据,更进一步,需要实现对数据表中数据的模糊查询功能.本文就讲讲述如何用C#实现combobox下拉列表的模糊查 ...
- 【菜鸟玩Linux开发】通过MySQL自动同步刷新Redis
在服务端开发过程中,一般会使用MySQL等关系型数据库作为最终的存储引擎,Redis其实也可以作为一种键值对型的数据库,但在一些实际场景中,特别是关系型结构并不适合使用Redis直接作为数据库.这俩家 ...
随机推荐
- el 表达式遍历Map
el 表达式遍历Map<c:forEach var="item" items="${payMentMap}"> <option value=& ...
- 并发编程(四):ThreadLocal从源码分析总结到内存泄漏
一.目录 1.ThreadLocal是什么?有什么用? 2.ThreadLocal源码简要总结? 3.ThreadLocal为什么会导致内存泄漏? 二.ThreadLoc ...
- 框架基础:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码
距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这个行业,让大脑休息一下.一个人旅行,一个人休息,正好也去完成一个目标 --- 拥有自己的驾照.当然,也把自己晒的黑漆马虎的.不过这一段时间 ...
- (cljs/run-at (JSVM. :all) "一起实现柯里化")
前言 习惯了Ramda.js就会潜意识地认为函数均已柯里化,然后就可以随心所欲的用函数生成函数,或者使用compose组合多个函数来生成一个新函数.如下 const f = a => b =& ...
- MacTex XeLaTex xdvipdfmx:fatal: pdf_ref_obj(): passed invalid object. 报错的解决方法
在使用MacTex配合TexStudio编译beamer的时候,爆出如下错误, xdvipdfmx:fatal: pdf_ref_obj(): passed invalid object. 结果尝试其 ...
- (转载)DBCP、C3P0、Proxool 、 BoneCP开源连接池的比较
原文链接: http://blog.csdn.net/miclung/article/details/7231553 简介 使用评价 项目主页 DBCP DBCP是一个依赖Jakarta ...
- mybatis存取blob对象+@Cacheable实现数据缓存
参考文档: http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ 需求场景: 当前业务通过第三方接口查询一个业务数据, ...
- Student implements java.io.Serializable
package JBJADV003; public class Student implements java.io.Serializable { private String name; priva ...
- centos7安装图形化界面
yum groups install -y "GNOME Desktop" "Graphical Administration Tools"
- C# 百分比的获取
这里介绍 C# 百分比转换有2种方式 例: double a=50; double b=100; a/b.ToString("0.00%"); 或 a/b.ToString(&qu ...