一、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的更多相关文章

  1. SqlServer和MySQL游标学习

    一 sqlserver游标使用 /*** 游标的使用  讲了这个多游标的优点,现在我们就亲自来揭开游标的神秘的面纱.  使用游标的顺序: 声名游标.打开游标.读取数据.关闭游标.删除游标. 1.3.1 ...

  2. MySQL游标操作指南

    本篇文章是对MySQL游标的具体使用进行了详细的分析介绍,需要的朋友参考下   测试表 level  代码如下: create table test.level (name varchar(20)); ...

  3. 个人笔记mysql游标

    经过测试,mysql游标是无法读取自定义函数计算的结构,mysql自带的函数计算值是可以读取的.

  4. MySQL游标的简单实践

    Q:为什么要使用游标? A: 在存储过程(或函数)中,如果某条select语句返回的结果集中只有1行,可以使用select into语句(上几篇博客有介绍到用法)来得到该行进行处理:如果结果集中有多行 ...

  5. [转]MySQL游标的使用

    转自:http://www.cnblogs.com/sk-net/archive/2011/09/07/2170224.html 以下的文章主要介绍的是MySQL游标的使用笔记,其可以用在存储过程的S ...

  6. Mysql 游标初识

    MySql 游标初识 认识 游标(cursor), 按字面意思可理解为, 游动的标识, 或者叫做"光标", 这样更容易理解. 就好比现有一张表存储了n行记录, 然后我想每次取出一行 ...

  7. java jdbc使用SSH隧道连接mysql数据库demo

    java jdbc使用SSH隧道连接mysql数据库demo   本文链接:https://blog.csdn.net/earbao/article/details/50216999   packag ...

  8. MySQL PLSQL Demo - 003.静态游标

    drop procedure if exists p_hello_world; create procedure p_hello_world() begin declare id integer; ) ...

  9. MySQL 游标

    概述 本章节介绍使用游标来批量进行表操作,包括批量添加索引.批量添加字段等.如果对存储过程.变量定义.预处理还不是很熟悉先阅读我前面写过的关于这三个概念的文章,只有先了解了这三个概念才能更好的理解这篇 ...

随机推荐

  1. layUI模块化框架

    layUI的API 文档 https://www.layui.com/doc/element/progress.html API文档中有许多demo 以及相关属性的详细介绍

  2. Java基础知识--集合

    集合类 数组和集合的比较:数组可以存储对象,也可以存储基本数据类型,但是缺点就是长度固定,不能改变:集合长度是可变的,但是集合只能存储对象,集合可以存储不同类型的对象. Java容器类库一共有两种主要 ...

  3. JDBC接口

    Jmeter实例8:JDBC接口 加线程组.加JDBC配置信息: 配置信息详情如下:默认展示值不用修改 必填信息: Database UR:固定格式,将IP.端口号.数据库名修改成自己要用的数据库信息 ...

  4. ios真机中Text组件出现多余边框

    问题 ios真机中Text组件出现多余边框(模拟器不会出现,真机会出现该问题). 原因 在ios启动页设置中,预设的尺寸要求与设置中图片尺寸不符合导致屏幕精度计算出现问题(启动屏分辨率错误设置会导致手 ...

  5. POJ1068 --(模拟)

    这题是在看一个书的时候的一个例题,当时并不明白啥意思,于是便找了下原题,以前没在POJ上刷过,这是开了个头,以后努力刷这个网站 题目大概意思是:http://poj.org/problem?id=10 ...

  6. oracle 占比函数

    这个函数在oracle帮助文档的位置:SQL Reference里面,很好找的. 除报告详细数据外,许多报告中还包括每行总数的百分比.例如,每名客户的订单相对于总订单的百分比,或每位销售代表的销售额相 ...

  7. 【数论】Factors of Factorial @upcexam6503

    问题 G: Factors of Factorial 时间限制: 1 Sec  内存限制: 128 MB提交: 57  解决: 33[提交][状态][讨论版][命题人:admin] 题目描述 You ...

  8. Javascript正则表达入参是null

    今天群友问了一个问题,如下的执行结果是什么? var reg = /^[a-z0-9\u4e00-\u9fa5]{0,15}$/; console.log(reg.test(null)); // tr ...

  9. tensorflow 在加载大型的embedding模型参数时,会遇到cannot be larger than 2GB

    这种问题是,对于每一个变量 variable 由于是基于protobuf存在这大小限制(2G),这个时候,我们需要将embedding拆开,拆分成N等分,来使得每一个 variable都在2G以下; ...

  10. 一个会学习(观察->活学->求变)的人,在任何领域都能变得强大无比

      开始今天的话题之前,我说个小故事.   很早以前有一部美剧,叫<Hero>.   大概讲的是正反两派都是一群有超能力的人,彼此为了某个巨大的阴谋互相撕逼了十多集.虽然剧情很老套,但是让 ...