MySQL 游标的基本用法

MySQL游标只能用于存储过程。
使用游标的步骤:
①在能够使用游标前,必须声明它。这个过程实际上没有检索数据,它只是定义要使用的select语句。
游标的定义格式:
DECLARE 光标名称 CURSOR FOR 查询语法
declare cursor_name cursor for select_statement

②声明游标后,要打开游标以供使用。这个过程就是把前面定义的select语句把数据实际检索出来。
打开游标格式:
OPEN 光标名称
open cursor_name

③对于填有数据的游标,根据需要取出(检索)各行。
在游标被打开后,使用fetch语句分别访问它的每一行。fetch指定检索的列,并存储到已定义好的列中。然后继续向前移动游标中的内部行指针,使下一条fetch语句检索下一行(不重复读取同一行)。
取游标中的数据格式:
FETCH 光标名称 INFO var_name [,var_name ].....
fetch cursor_name info var_name

④在结束游标使用后,必须关闭游标。
关闭游标
CLOSE curso_name;
close 光标名称

创建部门表:

CREATE TABLE IF NOT EXISTS depart(
    bumenTableid INT(11) NOT NULL primary key auto_increment COMMENT'部门编号(主键)',
    bumenTablename VARCHAR(50) COMMENT'部门名称',
    bumenTableaddress VARCHAR(50) COMMENT'部门地址'
);

添加部门表数据:

INSERT INTO  depart(bumenTablename,bumenTableaddress) VALUES 
('销售部','销售部地址'),
('学业部','学业部地址'),
('董事部','董事部地址'),
('人力资源部','人力资源部地址'),
('产品部','产品部地址');

创建员工表:

CREATE TABLE emp(
    id INT(11) NOT NULL primary key auto_increment COMMENT'员工编号',
    yuangongname VARCHAR(50) COMMENT'员工姓名',
    word VARCHAR(50) COMMENT'员工工作',
    lineManagerId INT(11) COMMENT'员工直属领导编号',
    entryTime datetime COMMENT'员工入职时间',
    wage INT(11) COMMENT'员工工资',
    bonus INT(11) COMMENT'员工奖金',
    bumenTableId INT(11) NOT NULL COMMENT'对应部门表的外键',
    FOREIGN KEY(bumenTableId) REFERENCES  depart(bumenTableid)
);

添加员工表数据:

INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小王', '职员', '2', '2017-06-14 14:30:50', '4000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小李', '销售经理', '4', '2016-08-16 14:32:08', '20800', '5000', '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小张', '产品经理', '4', '2016-05-04 14:33:05', '22700', null, '5');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小高', '职员', null, '2015-07-08 14:33:54', '5000', null, '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小刘', 'HR经理', '4', '2017-11-08 14:35:35', '10000', null, '4');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('王一', '学业经理', '4', '2016-11-01 14:36:28', '20000', '5000', '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('王二', '职员', '3', '2018-03-22 14:38:44', '5000', null, '5');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李四', '职员', '5', '2017-04-01 14:39:53', '5000', null, '4');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李一', '职员', '6', '2018-08-01 14:40:43', '5000', null, '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李二', '职员', '2', '2018-05-17 14:41:30', '5000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李三', '职员', '2', '2017-05-01 14:42:20', '5000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('公司人员', '其他', null, '2015-07-08 15:31:52', '1234567', '1234567', '5');

示例1(游标返回单条记录):查询某个员工的姓名,职位、工资等

DROP PROCEDURE IF EXISTS pro_empIndepart;

delimiter //
CREATE PROCEDURE pro_empIndepart (IN empid INT)
    READS SQL DATA
BEGIN
    DECLARE  c_id INT;
    DECLARE  c_empname VARCHAR(50);
    DECLARE  c_job VARCHAR(50);
    DECLARE  c_salary INT;
    DECLARE cur CURSOR for select  e.id,e.yuangongname,e.word,e.wage from emp e where  e.id =  empid;    
    OPEN cur;
        FETCH cur INTO c_id,c_empname,c_job,c_salary;
        SELECT c_id,c_empname,c_job,c_salary;
    CLOSE cur;
END//

delimiter ;

调用存储过程:

CALL pro_empIndepart(5);
image.png

上述示例返回的是单条记录,所以不需要遍历结果集。

示例2(游标返回结果集):查询某个部门下员工信息

DROP PROCEDURE IF EXISTS empIndepart_list;

delimiter //
create procedure empIndepart_list(IN departid INT)
begin
    declare done boolean default 0;
    DECLARE  c_id,c_salary INT;
  -- 注意 接收游标值为中文时 需要 给变量 指定 字符集为utf8
  DECLARE  c_empname,c_job VARCHAR(50) character set utf8;

    declare cur cursor
            for
          select  e.id,e.yuangongname,e.word,e.wage from emp e where e.bumenTableId=departid;
  declare continue handler for sqlstate '02000' set done=1;
    create table if not  exists emp_dempart_temp(id int,empname VARCHAR(50),job VARCHAR(50),salary int);
  truncate TABLE emp_dempart_temp;

    open cur;
         REPEAT
            fetch cur into  c_id,c_empname,c_job,c_salary;
                if done != 1 then
                    insert into emp_dempart_temp(id,empname,job,salary) values(c_id,c_empname,c_job,c_salary);
        end if;
    until done =1 end repeat;
    close cur;
  
end//
delimiter;

该示例,使用fetch检索指定列到声明的4个变量中。但与上一个例子不同的是,这个fetch是在repeat内,因为它反复执行直到done为真(由 until done =1 end repeat;规定)。为了使该语句起作用,用一个default 0来定义变量done。那么done怎样才能在结束时被设置为真呢?要使用以下语句:

declare continue handler for SQLSTATE '02000' SET done=1;

该语句定义了一个continue handler,它是在条件出现时被执行的代码。当SQLSTATE‘02000’出现时,set done=1。SQLSTATE’02000’是一个未找到条件,当REPEAT由于没有更多的行供循环而不能继续时,出现该条件。

注意:用declare定义的局部变量必须在定义任意游标或句柄之前定义,而句柄必须在游标之后定义(例如上面done语句)。不遵守此顺序将产生错误消息。

执行该存储过程,它将定义几个变量和一个continue handler,定义并打开一个游标,重复读取所有行,在fetch语句之后,循环结束之前可以在循环内放入任意需要的处理,例如向临时表中插入数据,查询某变量的值等。
上述示例,在打开游标之前创建了一个临时表:emp_dempart_temp,在遍历游标查询结果时,在满足done != 1的条件下向该表插入 存储过程中游标查询生成的结果。

调用存储过程:

CALL empIndepart_list(2);

使用select语句查看emp_dempart_temp的内容:

select * from emp_dempart_temp;
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容