Mysql - 游标/动态sql/事务
游标这个在我目前的项目里面用的还不多, 但是其功能还是很强大的.
动态sql以前都没用过, 是跟着富士康(不是张全蛋的富土康哦)过来的同事学的. 还是挺好用的. 我的数据库方面, 跟他学了不少. 在此, 感谢他一下, 建华锅锅.
事务在前面的篇章中其实已经出现过了, 这个东西好像还是程序中用的比较多一点.
由于之前的工作中碰到过一个场景, 正好将游标,动态sql,事务都用上了, 那么我也弄一个例子好了, 想了一个别的场景, 与工作的那个场景不相干, 并没有泄露公司业务机密之类的啊.
先看例子吧, 然后在后面, 我补上语法.
一、例子
1. 建表
既然是讲例子, 当然不能忘记建表嘛, 从0开始.
create table Goods
(
Id int not null PRIMARY key auto_increment,
Code varchar() comment '编码',
Name varchar() comment '名称',
Count int comment '数量',
Brand varchar() comment '品牌'
) default charset=utf8 comment '商品表'; create table GoodDetails
(
Id int not null PRIMARY key auto_increment,
GId int not null comment 'Goods表Id',
Name varchar() comment '名称',
Code varchar() comment '编码明细',
Remark varchar() comment '备注'
) default charset=utf8 comment '商品明细';
2. 加入基础数据

3. 虚拟场景介绍
公司最近进了一批物品, 就是上面的Goods表了, 并且准备给每一个物品进行编码(编码规则就是用Goods表的Code加上流水号, 去生成), 并打上条形码.
这里的功能就是生成商品明细和流水号的问题了, 一键生成. 这里通常的实现方式有两种:
方式一 : 程序生成
在程序中, 读取需要生成的数据, 比如上面这四条, 然后循环每一条, 给数据加上编码, 总共生成出12条数据, 在吧这12条数据, 存入明细表中. 在数据量少的时候还好, 完全可以接受, 但是如果数据量多了, 那速度, 慢的让人有砸电脑的冲动. Goods表的几条数据, 到GoodDetails表中, 会变成数百, 甚至上千, 上万.
方式二 : 数据库生成
如果不想读取出来再插入, 并且逻辑处理并不多,不复杂的情况下, 可以使用数据库去生成. 还是很方便的, 速度也提升非常多.
那这里, 我只介绍方式二了, 方式一, 只是处理麻烦一点.
4. 脚本:
delimiter $
drop PROCEDURE if EXISTS p_autocreate;
CREATE PROCEDURE `p_autocreate`(IN g_ids VARCHAR(1000), IN nolength INT)
BEGIN
DECLARE res_code INT; DECLARE res_msg VARCHAR (50); /*临时表的条数*/
DECLARE t_count INT; /**游标内使用变量**begin**/
DECLARE g_id INT; DECLARE g_code VARCHAR (50); DECLARE d_code VARCHAR (50); DECLARE g_count INT (11); DECLARE g_name VARCHAR (20);
/**游标内使用变量**end**/ /**游标的位置**/
DECLARE v_index INT DEFAULT 1; DECLARE done BIT DEFAULT 0; /*声明游标*/
DECLARE g_cursor CURSOR FOR SELECT id, CODE, NAME, COUNT FROM temp_goods; /*游标查询时, 如果找不到下一个了, 会将done置为1*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; /**创建临时表**begin**/
DROP TABLE IF EXISTS temp_goods;
CREATE TEMPORARY TABLE temp_goods (
Id INT NOT NULL, -- PRIMARY key auto_increment,
CODE VARCHAR (50),
NAME VARCHAR (20),
COUNT INT
) DEFAULT CHARSET = utf8;
/**创建临时表**end**/ /**初始化返回值**begin**/
SET res_code := "-99"; SET res_msg := "OK";
/**初始化返回值**end**/ IF (g_ids IS NOT NULL OR LENGTH(g_ids) > 0) THEN
SET @v_sql := CONCAT("INSERT INTO temp_goods(Id,Code,Name,Count) ",
" select Id,Code,Name,Count from Goods ",
" where ",
" find_in_set(id, ",
CHAR(34),
g_ids,
CHAR(34),
")>0 ;"); /*预编译此动态sql, 并存入stmt中*/
PREPARE stmt FROM @v_sql; /*执行此动态sql, 此动态sql的作用, 是从Goods中提取有效数据*/
EXECUTE stmt; /*释放此资源*/
DEALLOCATE PREPARE stmt; SELECT COUNT(1) INTO t_count FROM temp_goods; START TRANSACTION; -- 开始事务 IF (t_count > 0) THEN
/*打开游标*/
OPEN g_cursor; REPEAT
/*这里的顺序要与之前的顺序保持一致*/
FETCH g_cursor INTO g_id, g_code, g_name, g_count; IF NOT done THEN SET v_index := 1; IF (IFNULL(g_count, 0) > 0) THEN WHILE (v_index <= g_count)
DO
SET d_code := CONCAT(g_code, LPAD(v_index, nolength, "0")); INSERT INTO GoodDetails(GId, NAME, CODE) VALUES (g_id, g_name, d_code); SET v_index := v_index + 1;
END WHILE;
END IF;
END IF;
UNTIL done END REPEAT; -- 结束repeat循环
CLOSE g_cursor; /*关闭游标*/ COMMIT; -- 提交事务 ELSE ROLLBACK; -- 回滚事务 SET res_code := "10"; SET res_msg := "系统中不存在相关记录.";
END IF;
ELSE
SET res_code := "5"; SET res_msg := "请选择要生成的记录";
END IF; DROP TABLE IF EXISTS temp_goods; SELECT res_msg;
END $
delimiter ;
5. 结果:
执行这个存储过程
call p_autocreate('1,2,3,4', 3);

ok, 执行成功, 接下来, 来看一下GoodDetails表的数据:

我这里的例子, 已经是最简单的一个例子了, 在实际使用过程中, 可能比这个还要复杂一些, 数据更多一些.
不过说到这个数据量, 我倒不介意, 多做一个实验.
6. 实验
我将各自的数据量, 都修改为 10000, 如下图, 这个时候, 要生成 40000 条数据, 并且插入到表中去. 如果使用程序处理插入数据库的方式, 确实会慢一些.

数据库的方式, 确实会快很多. 如下图, 生成4w条数据, 然后插入GoodDetails表中, 花了不到4s的时间. 算是一个比较快的时间了.

OK, 接下来, 就来介绍一下他们的语法.
二、游标
1. 语法
1.1 声明游标
declare 游标名 cursor for select 列名 from 表
1.2 打开游标
open 游标名
1.3 游标前进
fetch 游标名 into 变量a, 变量b ...
1.4 关闭游标
close 游标名
2. 注
既然游标执行的方式, 像是一个循环, 那么什么时候才知道这个循环要结束呢.
例子里面, 有一句话, DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 这句话的意思, 其实就是当游标找不到下一条数据的时候, 就回将变量 done 修改为1.
三、动态sql
1. 语法
1.1 准备sql变量
此sql变量必须是字符串格式的哦. 这样可以动态生成需要执行的sql.
1.2 预编译
PREPARE stmt FROM @v_sql;
这里的stmt是一个变量, 名称自己取
1.3 执行
EXECUTE stmt;
1.4 释放资源
DEALLOCATE PREPARE stmt;
四、事务
1. 语法
到这里, 我突然不知道说些什么了. 那就简单介绍下吧
1.1 开始事务
start transation;
1.2 提交事务
commit;
1.3 回滚事务
rollback;
Mysql - 游标/动态sql/事务的更多相关文章
- MySQL存储过程动态SQL语句的生成
用Mysql存储过程来完成动态SQL语句,使用存储过程有很好的执行效率: 现在有要求如下:根据输入的年份.国家.节假日类型查询一个节假日,我们可以使用一般的SQL语句嵌入到Java代码中,但是执行效率 ...
- mysql 存储过程 动态sql例子
proc:BEGIN ; ; ; ) DEFAULT ''; ) DEFAULT ''; ) DEFAULT '';#插入日志的表,一个活动一张表 #将局部变量转换成会话变量 #动态sql语言只接受会 ...
- MySQL基础----动态SQL语句
尊重原创:http://blog.csdn.net/abc19900828/article/details/39501643 动态sql语句基本语法 1 :普通SQL语句可以用Exec执行 eg: ...
- mysql游标的用法及作用
1当前有三张表A.B.C其中A和B是一对多关系,B和C是一对多关系,现在需要将B中A表的主键存到C中:常规思路就是将B中查询出来然后通过一个update语句来更新C表就可以了,但是B表中有2000多条 ...
- MyBatis 的动态 SQL 使用说明
动态SQL简介 参考文档地址:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 ...
- MySQL通过视图(或临时表)实现动态SQL(游标)
>参考de优秀文章 写MySQL存储过程实现动态执行SQL Dynamic cursor in stored procedure MySQL通过视图(或临时表)实现动态SQL(游标). 因在实现 ...
- 使用动态SQL处理table_name作为输入参数的存储过程(MySQL)
关于mysql如何创建和使用存储过程,参考笔记<MySQL存储过程和函数创建>以及官网:https://dev.mysql.com/doc/refman/5.7/en/create-pro ...
- MyBatis基础_连接池与事务、动态SQL、注解开发
一.MyBatis连接池及事务控制 1.连接池 在实际开发中,都会使用连接池,因为它可以减少获取连接缩消耗的时间.所谓连接池,就是存储数据库连接的容器.连接池中存储一定数量的数据库连接,当线程需要使用 ...
- 游标、动态sql、异常
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlIAAAFeCAIAAADBl2bCAAAgAElEQVR4nOyddXgU197H12OEELxIkV
随机推荐
- python3 threading初体验
python3中thread模块已被废弃,不能在使用thread模块,为了兼容性,python3将thread命名为_thread.python3中我们可以使用threading进行代替. threa ...
- 使用 Roslyn 编译器服务
.NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为 ...
- react入门参考资料--step by step
ReactJS简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站.做出 ...
- MAVEN学习-第一个Maven项目的构建
MAVEN安装成功之后就可以进行项目的构建和管理了: 为什么要用maven进行项目的构建和管理? 对于初学者来说一个最直接的也是最容易里的优点在于JAR包的管理,相对于以前开发一个项目的时候我们需要用 ...
- FullCalendar日历插件说明文档
FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...
- JDBC MySQL 多表关联查询查询
public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver&q ...
- Springboot搭建web项目
最近因为项目需要接触了springboot,然后被其快速零配置的特点惊呆了.关于springboot相关的介绍我就不赘述了,大家自行百度google. 一.pom配置 首先,建立一个maven项目,修 ...
- spider RPC入门指南
本部分将介绍使用spider RPC开发分布式应用的客户端和服务端. spider RPC中间件基于J2SE 8开发,因此需要确保服务器上安装了JDK 8及以上版本,不依赖于任何额外需要独立安装和配置 ...
- nginx服务器安装及配置文件详解
nginx在工作中已经有好几个环境在使用了,每次都是重新去网上扒博客,各种编译配置,今天自己也整理一份安装文档和nginx.conf配置选项的说明,留作以后参考.像负载均衡配置(包括健康检查).缓存( ...
- grep 查找bash脚本中的注释代码
出于安全性的考虑,不建议在bash脚本中注释掉不使用的代码.也就是说如果某段代码不使用了,那么应该删除掉,而不是简单地注释掉.假如你突然意识到这一点,而以前并没有遵从这个原则,现在需要找出脚本中的注释 ...