场景:需要插入50万个数据,分10次插入,每次查词5万条数据
-- 部门表
create table dept(
id int unsigned primary key auto_increment,
-- 部门号
deptno mediumint unsigned not null default 0,
-- 部门名称
dname varchar(20) not null default "",
-- 楼层位置
loc varchar(13) not null default ""
)engine=innodb default charset=GBK;
-- 员工表
CREATE TABLE emp(
id int unsigned primary key auto_increment,
-- 员工编号
empno mediumint unsigned not null default 0,
-- 员工名字
ename varchar(20) not null default "",
-- 工作
job varchar(9) not null default "",
-- 上级编号
mgr mediumint unsigned not null default 0,
-- 入职时间
hiredate date not null,
-- 薪水
sal decimal(7,2) not null,
-- 红利
comm decimal(7,2) not null,
-- 部门编号
deptno mediumint unsigned not null default 0
)ENGINE=INNODB DEFAULT CHARSET=GBK;
由于开启过慢查询日志,开启了bin-log
,我们就必须为function
指定一个参数,否则使用函数会报错。
# log_bin_trust_function_creators 默认是关闭的 需要手动开启
mysql> SHOW VARIABLES LIKE 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF |
+---------------------------------+-------+
1 row in set (0.00 sec)
mysql> SET GLOBAL log_bin_trust_function_creators=1;
Query OK, 0 rows affected (0.00 sec)
上述修改方式MySQL重启后会失败,在配置文件my.ini/my.cnf下添加如下配置之后修改永久有效。
[mysqld]
# 如果上面的不行,就换成下面的
log_bin_trust_function_creators=ON
log_bin_trust_function_creators=1
-- 本来执行一段sql的结束符号是;,但是因为函数里面有;,先将结束符号修改为$$
DELIMITER $$
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
-- 声明一个字符串并赋值
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
-- CONCAT:拼接;SUBSTRING:截取
SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END $$
DELIMITER $$
CREATE FUNCTION rand_num() RETURNS INT(5)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(100 + RAND() * 10);
RETURN i;
END $$
DELIMITER $$
-- IN START INT(10),IN max_num INT(10):从什么时候开始,到什么时候结束
CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
-- 将自动提交设置为零,后面批量提交,提高插入效率
SET autocommit = 0;
-- 循环
REPEAT
SET i = i + 1;
-- 插入数据
INSERT INTO dept(deptno,dname,loc) VALUES((START + i),rand_string(10),rand_string(8));
-- 循环的结束条件
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
DELIMITER $$
CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES((START + i),rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
如果存储过程有问题,需要先删除原本的存储过程,再创建新的存储过程
drop PROCEDURE insert_emp;
# 调用存储过程向dept表插入10个部门,id从100开始。
# 改回;结束
DELIMITER ;
CALL insert_dept(100,10);
# 调用存储过程向emp表插入50万条数据。
DELIMITER ;
CALL insert_emp(100001,500000);
mysql> -- 本来执行一段sql的结束符号是;,但是因为函数里面有;,先将结束符号修改为$$
mysql> DELIMITER $$
mysql> CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
-> BEGIN
-> -- 声明一个字符串并赋值
-> DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-> DECLARE return_str VARCHAR(255) DEFAULT '';
-> DECLARE i INT DEFAULT 0;
-> WHILE i < n DO
-> -- CONCAT:拼接;SUBSTRING:截取
-> SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
-> SET i = i + 1;
-> END WHILE;
-> RETURN return_str;
-> END $$
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER $$
mysql> CREATE FUNCTION rand_num() RETURNS INT(5)
-> BEGIN
-> DECLARE i INT DEFAULT 0;
-> SET i = FLOOR(100 + RAND() * 10);
-> RETURN i;
-> END $$
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> DELIMITER $$
mysql> -- IN START INT(10),IN max_num INT(10):从什么时候开始,到什么时候结束
mysql> CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))
-> BEGIN
-> DECLARE i INT DEFAULT 0;
-> -- 将自动提交设置为零,后面批量提交,提高插入效率
-> SET autocommit = 0;
-> -- 循环
-> REPEAT
-> SET i = i + 1;
-> -- 插入数据
-> INSERT INTO dept(deptno,dname,loc) VALUES((START + i),rand_string(10),rand_string(8));
-> -- 循环的结束条件
-> UNTIL i = max_num
-> END REPEAT;
-> COMMIT;
-> END $$
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> DELIMITER $$
mysql> CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))
-> BEGIN
-> DECLARE i INT DEFAULT 0;
-> SET autocommit = 0;
-> REPEAT
-> SET i = i + 1;
-> INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES((START + i),rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());
-> UNTIL i = max_num
-> END REPEAT;
-> COMMIT;
-> END $$
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> -- 调用存储过程向dept表插入10个部门,id从100开始。
mysql> -- 改回;结束
mysql> DELIMITER ;
mysql> CALL insert_dept(100,10);
Query OK, 0 rows affected (0.01 sec)
mysql> select * from dept;
+----+--------+------------+----------+
| id | deptno | dname | loc |
+----+--------+------------+----------+
| 1 | 101 | wcUtjNoeHY | UCcGZduM |
| 2 | 102 | BsHUBXkijy | MrwiAcLz |
| 3 | 103 | mLUrbdokks | iOsAsKiL |
| 4 | 104 | gzcMDIDTKQ | aGdznPkG |
| 5 | 105 | zFDbskEuiG | HsQcOMsB |
| 6 | 106 | FyCoNWwssm | QtvWssWn |
| 7 | 107 | BTOmVPnXVM | ZKBDoHtW |
| 8 | 108 | DcAsLkUTHF | hSRHLGYb |
| 9 | 109 | iOtBBcJopJ | BEtgAgfh |
| 10 | 110 | wMwUjmFsYM | PQGLKrEW |
+----+--------+------------+----------+
10 rows in set (0.00 sec)
mysql> DELIMITER ;
mysql> CALL insert_emp(100001,500000);
Query OK, 0 rows affected (39.19 sec)
本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。