mysql 游标 demo
一、MySQL游标的概念
1、游标介绍
MySQL的游标(cursor)是一个重要的概念,通过查找资料与自己的理解,主要得出以下几点关于自己的理解。
有数据缓冲的思想:游标的设计是一种数据缓冲区的思想,用来存放SQL语句执行的结果。 先有数据基础:游标是在先从数据表中检索出数据之后才能继续灵活操作的技术。 类似于指针:游标类似于指向数据结构堆栈中的指针,用来pop出所指向的数据,并且只能每次取一个。
2、游标优缺点:
(1)游标的优点:
因为游标是针对行操作的,所以对从数据库中select查询得到的每一行可以进行分开的独立的相同或不同的操作,是一种分离的思想。可以满足对某个结果行进行特殊的操作。 游标与基于游标位置的增删改查能力。 MySQL数据库中没有专门描述一行的表达形式,但这是需要的,所以,个人理解的话,我觉得游标是在关系数据库这种面向集合的系统中抽离出来,单独针对行进行表达(也可以理解成网上资料说的:游标是面向集合与面向行的设计思想之间的一种桥梁)
(2)游标缺点
游标的缺点是针对有点而言的,也就是只能一行一行操作,在数据量大的情况下,是不适用的,速度过慢。这里有个比喻就是:当你去ATM存钱是希望一次性存完呢,还是100一张一张的存,这里的100一张一张存就是游标针对行的操作。 数据库大部分是面对集合的,业务会比较复杂,而游标使用会有死锁,影响其他的业务操作,不可取。 当数据量大时,使用游标会造成内存不足现象。
3、游标的使用场景
针对游标的优缺点,我总结游标的使用场景,主要用在循环处理、存储过程、函数中使用,用来查询结果集,就比如:我们需要从表中循环判断并得到想要的结果集,这时候使用游标操作很方便速度也很快。
二、游标的使用
1、游标的使用步骤
游标的使用一般分为5个步骤,主要是:定义游标->打开游标->使用游标->关闭游标->释放游标。
(1).定义游标
DECLARE <游标名> CURSOR FOR select语句;
-- 声明游标
DECLARE my_cursor CURSOR FOR select style_id,id from car_type;
(2).打开游标
open <游标名>
-- 打开游标
OPEN my_cursor;
(3).使用游标
使用游标需要用关键字fetch来取出数据,然后取出的数据需要有存放的地方,我们需要用declare声明变量存放列的数据其语法格式为:
declare 变量1 数据类型(与列值的数据类型相同)
declare 变量2 数据类型(与列值的数据类型相同)
declare 变量3 数据类型(与列值的数据类型相同)
-- 需要定义接收游标数据的变量
DECLARE styleId bigint(19);
DECLARE typeId bigint(19);
-- 遍历数据结束标志
DECLARE done INT DEFAULT FALSE;
-- 将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 打开游标
OPEN my_cursor;
-- 开始循环
read_loop: LOOP
-- 提取游标里的数据,这里只有一个,多个的话也一样;
FETCH cur INTO styleId,typeId;
-- 声明结束的时候
IF done THEN
LEAVE read_loop;
END IF;
-- 这里做你想做的循环的事件
INSERT INTO `test` VALUES (a,b) ON DUPLICATE KEY UPDATE `a`=c;
END LOOP;
(4).关闭游标:
-- 关闭游标
CLOSE my_cursor;
(5).释放游标
demo :
-- 定义的游标变量和游标中使用的变量,必须定义在变量之后。
-- 在MySql中,造成游标溢出时会引发mysql预定义的NOT FOUND错误,
-- 所以在上面使用下面的代码指定了当引发not found错误时定义一个continue 的事件,指定这个事件发生时修改done变量的值。
use das;
-- 查看存储过程
SHOW PROCEDURE STATUS; -- 显示pro存储过程的详细信息
SHOW CREATE PROCEDURE pro; -- 删除pro存储过程
DROP PROCEDURE IF EXISTS pro; select style_id,id from car_type; select count(1) from car_type; -- 创建简单的存储过程
DELIMITER //
DROP PROCEDURE IF EXISTS pro//
CREATE PROCEDURE pro()
BEGIN
-- 需要定义接收游标数据的变量
DECLARE styleId bigint(19);
DECLARE typeId bigint(19);
DECLARE co bigint(19) default 0;
-- 定义的游标变量和游标中使用的变量,必须定义在变量之后。
DECLARE done INT DEFAULT FALSE;
-- 定义游标
DECLARE my_cursor CURSOR FOR select style_id,id from car_type;
-- 在MySql中,造成游标溢出时会引发mysql预定义的NOT FOUND错误,
-- 所以在上面使用下面的代码指定了当引发not found错误时定义一个continue 的事件,指定这个事件发生时修改done变量的值。
DECLARE CONTINUE HANDLER for not found set done = true;
-- 打开游标
OPEN my_cursor;
-- 开始循环
read_loop: LOOP
-- 提取游标里的数据,这里只有一个,多个的话也一样;
FETCH my_cursor INTO styleId,typeId;
-- 声明结束的时候
IF done THEN
LEAVE read_loop;
END IF;
-- 这里做你想做的循环的事件
set co = co + 1;
END LOOP;
-- 关闭游标
CLOSE my_cursor;
select co;
END//
DELIMITER ; -- 调用存储过程
CALL pro();
demo :
-- getStockAmplitudeGoodsSum
use das; -- 创建简单的存储过程
DELIMITER //
DROP PROCEDURE IF EXISTS getStockAmplitudeGoodsSum //
CREATE PROCEDURE getStockAmplitudeGoodsSum(IN storeBaseId INT, IN productGoodsId INT, OUT totalAmount INT)
BEGIN
DECLARE type char(200);
DECLARE amount int(11);
declare clacAmount int(11) default 0;
declare co int(11) default 0;
DECLARE done INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR
SELECT f.type,e.amount
FROM stock_amplitude_goods as e left join stock_amplitude as f on e.stock_amplitude_id = f.id
WHERE f.store_base_id = storeBaseId and e.product_goods_id = productGoodsId;
DECLARE CONTINUE HANDLER for not found set done = true;
-- 打开游标
OPEN my_cursor;
-- 开始循环
read_loop: LOOP
-- 提取游标里的数据,这里只有一个,多个的话也一样;
FETCH my_cursor INTO type,amount;
-- 声明结束的时候
IF done THEN
LEAVE read_loop;
END IF;
IF type is not null THEN
set clacAmount = clacAmount + amount;
END IF;
END LOOP;
-- 关闭游标
CLOSE my_cursor;
set totalAmount = clacAmount;
END//
DELIMITER ;
-- pro
use das;
DELIMITER //
DROP PROCEDURE IF EXISTS pro//
CREATE PROCEDURE pro(IN storeBaseId INT)
BEGIN
declare brandId bigint(19);
declare brandName char(255);
declare seriesId bigint(19);
declare seriesName char(255);
declare styleId bigint(19);
declare styleName char(255);
declare typeId bigint(19);
declare typeName char(255);
declare serviceBaseId bigint(19);
declare serviceBaseName char(255);
declare serviceVariantId bigint(19);
declare serviceVariantName char(255);
declare productCategoryGoodsId bigint(19);
declare productCategorySuitType char(200);
declare amount int(11);
declare deficiency boolean default false; declare totalAmount int(11);
declare productGoodsId int(11); declare coTrue int default 0;
declare coFalse int default 0; DECLARE done INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR
select b.brand_id,b.brand_name,b.series_id,b.series_name,b.style_id,b.style_name,b.id as carTypeId, b.name as carTypeName,c.service_base_id,c.service_base_name,c.id as serviceVariantId,c.name as serviceVariantName,d.product_category_goods_id,d.product_category_suit_type,d.amount, true as _deficiency
from variant_car_type as a left join car_type as b on a.car_type_id = b.id
left join service_variant as c on a.service_variant_id = c.id
left join variant_goods as d on c.id = d.service_variant_id; DECLARE CONTINUE HANDLER for not found set done = true; CREATE TEMPORARY TABLE IF NOT EXISTS resultTable
(
brandId bigint(19),
brandName char(255),
seriesId bigint(19),
seriesName char(255),
styleId bigint(19),
styleName char(255),
typeId bigint(19),
typeName char(255),
serviceBaseId bigint(19),
serviceBaseName char(255),
serviceVariantId bigint(19),
serviceVariantName char(255),
productCategoryGoodsId bigint(19),
productGoodsId bigint(19),
productCategorySuitType char(200),
amount int(11),
totalAmount int(11),
deficiency boolean
);
truncate table resultTable; OPEN my_cursor;
read_loop: LOOP
FETCH my_cursor INTO brandId,brandName,seriesId,seriesName,styleId,styleName,typeId,typeName,serviceBaseId,serviceBaseName,serviceVariantId,serviceVariantName,productCategoryGoodsId,productCategorySuitType,amount,deficiency;
IF done THEN
LEAVE read_loop;
END IF;
IF productCategorySuitType is not null THEN
IF productCategorySuitType = 'COMMON_USE' THEN
call getStockAmplitudeGoodsSum(storeBaseId,productCategoryGoodsId,totalAmount);
set productGoodsId = productCategoryGoodsId;
IF amount > totalAmount THEN
set deficiency = true;
set coTrue = coTrue + 1;
ELSE
set deficiency = false;
set coFalse = coFalse + 1;
END IF;
ELSE
SELECT product_goods_id into productGoodsId FROM das.product_suit_car as g where g.product_category_id = productCategoryGoodsId and car_type_id = typeId;
call getStockAmplitudeGoodsSum(storeBaseId,productGoodsId,totalAmount);
IF amount > totalAmount THEN
set deficiency = true;
set coTrue = coTrue + 1;
ELSE
set deficiency = false;
set coFalse = coFalse + 1;
END IF;
END IF;
END IF;
insert into resultTable(
brandId,brandName,seriesId,seriesName,styleId,styleName,typeId,typeName,serviceBaseId,serviceBaseName,serviceVariantId,serviceVariantName,productCategoryGoodsId,productGoodsId,productCategorySuitType,amount,totalAmount,deficiency
)
values(
brandId,brandName,seriesId,seriesName,styleId,styleName,typeId,typeName,serviceBaseId,serviceBaseName,serviceVariantId,serviceVariantName,productCategoryGoodsId,productGoodsId,productCategorySuitType,amount,totalAmount,deficiency
);
END LOOP;
-- 关闭游标
CLOSE my_cursor;
select * from resultTable;
select coTrue/coFalse;
END//
DELIMITER ; call pro(2);
啦啦啦
啦啦啦
mysql 游标 demo的更多相关文章
- SqlServer和MySQL游标学习
一 sqlserver游标使用 /*** 游标的使用 讲了这个多游标的优点,现在我们就亲自来揭开游标的神秘的面纱. 使用游标的顺序: 声名游标.打开游标.读取数据.关闭游标.删除游标. 1.3.1 ...
- MySQL游标操作指南
本篇文章是对MySQL游标的具体使用进行了详细的分析介绍,需要的朋友参考下 测试表 level 代码如下: create table test.level (name varchar(20)); ...
- 个人笔记mysql游标
经过测试,mysql游标是无法读取自定义函数计算的结构,mysql自带的函数计算值是可以读取的.
- MySQL游标的简单实践
Q:为什么要使用游标? A: 在存储过程(或函数)中,如果某条select语句返回的结果集中只有1行,可以使用select into语句(上几篇博客有介绍到用法)来得到该行进行处理:如果结果集中有多行 ...
- [转]MySQL游标的使用
转自:http://www.cnblogs.com/sk-net/archive/2011/09/07/2170224.html 以下的文章主要介绍的是MySQL游标的使用笔记,其可以用在存储过程的S ...
- Mysql 游标初识
MySql 游标初识 认识 游标(cursor), 按字面意思可理解为, 游动的标识, 或者叫做"光标", 这样更容易理解. 就好比现有一张表存储了n行记录, 然后我想每次取出一行 ...
- java jdbc使用SSH隧道连接mysql数据库demo
java jdbc使用SSH隧道连接mysql数据库demo 本文链接:https://blog.csdn.net/earbao/article/details/50216999 packag ...
- MySQL PLSQL Demo - 003.静态游标
drop procedure if exists p_hello_world; create procedure p_hello_world() begin declare id integer; ) ...
- MySQL 游标
概述 本章节介绍使用游标来批量进行表操作,包括批量添加索引.批量添加字段等.如果对存储过程.变量定义.预处理还不是很熟悉先阅读我前面写过的关于这三个概念的文章,只有先了解了这三个概念才能更好的理解这篇 ...
随机推荐
- [jzoj]1729.blockenemy
Link https://jzoj.net/senior/#main/show/1729 Description 你在玩电子游戏的时候遇到了麻烦...... 你玩的游戏是在一个虚拟的城市里进行,这个城 ...
- git上传本地项目到github,方法2
第一步:去github上创建自己的Repository,创建页面如下图所示: 填写相应信息后点击create即可 Repository name: 仓库名称 Description(可选): 仓库描述 ...
- Office 2016 for Mac 64位16.14.1(180613)安装包&激活
注意,本页面是属于Mac操作系统使用的Office,如需Windows版的Office请点击下面的传送门. Windows版Office:https://www.itpwd.com/12.html 激 ...
- Java 深复制和浅复制
浅复制是指复制对象时仅仅复制对象本身(包括对象中的基本变量),而不复制对象包含的引用指向的对象.深复制不仅复制对象本身,而且复制对象包含的引用指向的对象. 复制对象时需要调用Object类的clone ...
- c# 后台绑定treeview 多个tab
<wijmo:C1Tabs ID="C1Tab1" runat="server" ><%--OnSelectedChanged="& ...
- strtok strchr strrchr strchrnul
NAME strchr, strrchr, strchrnul - locate character in string SYNOPSIS #include <strin ...
- 【组合数】微信群 @upcexam6016
时间限制: 1 Sec 内存限制: 128 MB 题目描述 众所周知,一个有着6个人的宿舍可以有7个微信群(^_^,别问我我也不知道为什么),然而事实上这个数字可以更大,因为每3个或者是更多的人都可以 ...
- ABAP语言实现 左移 <<、无符号右移 >>> 位移操作
这几天要在ABAP中实现 3DES 标准对称加密算法,与其他外部系统进行加密/解密操作.由于ABAP语言中没有 左移 <<.无符号右移 >>> 操作,只能自己实现 思路 ...
- Numba加速Python程序
众所周知,Python和Java一样是基于虚拟机的语言,并不是像C/C++那样将程序代码编译成机器语言再运行,而是解释一行执行一行,速度比较慢.使用Numba库的JIT技术编译以后,可以明显提高程序的 ...
- PL/SQL学习笔记之日期时间
一:PL/SQL时间相关类型 PL/SQL提供两个和日期时间相关的数据类型: 日期时间(Datetime)数据类型 时间间隔类型 二:日期时间类型 datetime数据类型有: DATE TIMEST ...