游标这个在我目前的项目里面用的还不多, 但是其功能还是很强大的.

动态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/事务的更多相关文章

  1. MySQL存储过程动态SQL语句的生成

    用Mysql存储过程来完成动态SQL语句,使用存储过程有很好的执行效率: 现在有要求如下:根据输入的年份.国家.节假日类型查询一个节假日,我们可以使用一般的SQL语句嵌入到Java代码中,但是执行效率 ...

  2. mysql 存储过程 动态sql例子

    proc:BEGIN ; ; ; ) DEFAULT ''; ) DEFAULT ''; ) DEFAULT '';#插入日志的表,一个活动一张表 #将局部变量转换成会话变量 #动态sql语言只接受会 ...

  3. MySQL基础----动态SQL语句

    尊重原创:http://blog.csdn.net/abc19900828/article/details/39501643   动态sql语句基本语法 1 :普通SQL语句可以用Exec执行 eg: ...

  4. mysql游标的用法及作用

    1当前有三张表A.B.C其中A和B是一对多关系,B和C是一对多关系,现在需要将B中A表的主键存到C中:常规思路就是将B中查询出来然后通过一个update语句来更新C表就可以了,但是B表中有2000多条 ...

  5. MyBatis 的动态 SQL 使用说明

    动态SQL简介 参考文档地址:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 ...

  6. MySQL通过视图(或临时表)实现动态SQL(游标)

    >参考de优秀文章 写MySQL存储过程实现动态执行SQL Dynamic cursor in stored procedure MySQL通过视图(或临时表)实现动态SQL(游标). 因在实现 ...

  7. 使用动态SQL处理table_name作为输入参数的存储过程(MySQL)

    关于mysql如何创建和使用存储过程,参考笔记<MySQL存储过程和函数创建>以及官网:https://dev.mysql.com/doc/refman/5.7/en/create-pro ...

  8. MyBatis基础_连接池与事务、动态SQL、注解开发

    一.MyBatis连接池及事务控制 1.连接池 在实际开发中,都会使用连接池,因为它可以减少获取连接缩消耗的时间.所谓连接池,就是存储数据库连接的容器.连接池中存储一定数量的数据库连接,当线程需要使用 ...

  9. 游标、动态sql、异常

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlIAAAFeCAIAAADBl2bCAAAgAElEQVR4nOyddXgU197H12OEELxIkV

随机推荐

  1. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  2. 关于ubuntu实机与虚机互相copy

    我的开发环境是在ubuntu上的,但是ubuntu上没有官方支持的QQ,有些不太方便,所以在上面虚了一个Win7(先是win10,但是win10最新版本太坑了,不说了),不过经常会出现复制文件,或者文 ...

  3. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  4. Android Ormlite 学习笔记1 -- 基础

    Ormlite 是一个开源Java数据实体映射框架.其中依赖2个核心类库: 1.ormlite-android-4.48.jar 2.ormlite-core-4.48.jar 新建项目,引用上面2个 ...

  5. MySQL主从环境下存储过程,函数,触发器,事件的复制情况

    下面,主要是验证在MySQL主从复制环境下,存储过程,函数,触发器,事件的复制情况,这些确实会让人混淆. 首先,创建一张测试表 mysql),age int); Query OK, rows affe ...

  6. 非关系型数据库(NoSql)

    最近了解了一点非关系型数据库,刚刚接触,觉得这是一个很好的方向,对于大数据 方面的处理,非关系型数据库能起到至关重要的地位.这里我主要是整理了一些前辈的经验,仅供参考. 关系型数据库的特点 1.关系型 ...

  7. Response.Redirect引起的性能问题分析

    现象: 最近做的一个系统通过单点登录(SSO) 技术验证用户登录.用户在SSO 系统上通过验证后,跳转到该系统的不同模块.而跳转的时间一直维持子啊几分钟左右. 分析步骤: 在问题复现时抓取Hang d ...

  8. 显示本地openssl支持的加密算法

    参考页面: http://www.yuanjiaocheng.net/webapi/parameter-binding.html http://www.yuanjiaocheng.net/webapi ...

  9. python enumerate 用法

    A new built-in function, enumerate() , will make certain loops a bit clearer. enumerate(thing) , whe ...

  10. 枚举:enum

    枚举 所谓枚举就是指定好取值范围,所有内容只能从指定范围取得. 例如,想定义一个color类,他只能有RED,GREEN,BLUE三种植. 使用简单类完成颜色固定取值问题. 1,就是说,一个类只能完成 ...