MySQL游標(biāo)只能用于存儲(chǔ)過程。
使用游標(biāo)的步驟:
①在能夠使用游標(biāo)前,必須聲明它。這個(gè)過程實(shí)際上沒有檢索數(shù)據(jù),它只是定義要使用的select語句。
游標(biāo)的定義格式:
DECLARE 光標(biāo)名稱 CURSOR FOR 查詢語法
declare cursor_name cursor for select_statement
②聲明游標(biāo)后,要打開游標(biāo)以供使用。這個(gè)過程就是把前面定義的select語句把數(shù)據(jù)實(shí)際檢索出來。
打開游標(biāo)格式:
OPEN 光標(biāo)名稱
open cursor_name
③對(duì)于填有數(shù)據(jù)的游標(biāo),根據(jù)需要取出(檢索)各行。
在游標(biāo)被打開后,使用fetch語句分別訪問它的每一行。fetch指定檢索的列,并存儲(chǔ)到已定義好的列中。然后繼續(xù)向前移動(dòng)游標(biāo)中的內(nèi)部行指針,使下一條fetch語句檢索下一行(不重復(fù)讀取同一行)。
取游標(biāo)中的數(shù)據(jù)格式:
FETCH 光標(biāo)名稱 INFO var_name [,var_name ].....
fetch cursor_name info var_name
④在結(jié)束游標(biāo)使用后,必須關(guān)閉游標(biāo)。
關(guān)閉游標(biāo)
CLOSE curso_name;
close 光標(biāo)名稱
創(chuàng)建部門表:
CREATE TABLE IF NOT EXISTS depart(
bumenTableid INT(11) NOT NULL primary key auto_increment COMMENT'部門編號(hào)(主鍵)',
bumenTablename VARCHAR(50) COMMENT'部門名稱',
bumenTableaddress VARCHAR(50) COMMENT'部門地址'
);
添加部門表數(shù)據(jù):
INSERT INTO depart(bumenTablename,bumenTableaddress) VALUES
('銷售部','銷售部地址'),
('學(xué)業(yè)部','學(xué)業(yè)部地址'),
('董事部','董事部地址'),
('人力資源部','人力資源部地址'),
('產(chǎn)品部','產(chǎn)品部地址');
創(chuàng)建員工表:
CREATE TABLE emp(
id INT(11) NOT NULL primary key auto_increment COMMENT'員工編號(hào)',
yuangongname VARCHAR(50) COMMENT'員工姓名',
word VARCHAR(50) COMMENT'員工工作',
lineManagerId INT(11) COMMENT'員工直屬領(lǐng)導(dǎo)編號(hào)',
entryTime datetime COMMENT'員工入職時(shí)間',
wage INT(11) COMMENT'員工工資',
bonus INT(11) COMMENT'員工獎(jiǎng)金',
bumenTableId INT(11) NOT NULL COMMENT'對(duì)應(yīng)部門表的外鍵',
FOREIGN KEY(bumenTableId) REFERENCES depart(bumenTableid)
);
添加員工表數(shù)據(jù):
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 ('小李', '銷售經(jīng)理', '4', '2016-08-16 14:32:08', '20800', '5000', '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小張', '產(chǎn)品經(jīng)理', '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經(jīng)理', '4', '2017-11-08 14:35:35', '10000', null, '4');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('王一', '學(xué)業(yè)經(jīng)理', '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(游標(biāo)返回單條記錄):查詢某個(gè)員工的姓名,職位、工資等
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 ;
調(diào)用存儲(chǔ)過程:
CALL pro_empIndepart(5);

上述示例返回的是單條記錄,所以不需要遍歷結(jié)果集。
示例2(游標(biāo)返回結(jié)果集):查詢某個(gè)部門下員工信息
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;
-- 注意 接收游標(biāo)值為中文時(shí) 需要 給變量 指定 字符集為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個(gè)變量中。但與上一個(gè)例子不同的是,這個(gè)fetch是在repeat內(nèi),因?yàn)樗磸?fù)執(zhí)行直到done為真(由 until done =1 end repeat;規(guī)定)。為了使該語句起作用,用一個(gè)default 0來定義變量done。那么done怎樣才能在結(jié)束時(shí)被設(shè)置為真呢?要使用以下語句:
declare continue handler for SQLSTATE '02000' SET done=1;
該語句定義了一個(gè)continue handler,它是在條件出現(xiàn)時(shí)被執(zhí)行的代碼。當(dāng)SQLSTATE‘02000’出現(xiàn)時(shí),set done=1。SQLSTATE’02000’是一個(gè)未找到條件,當(dāng)REPEAT由于沒有更多的行供循環(huán)而不能繼續(xù)時(shí),出現(xiàn)該條件。
注意:用declare定義的局部變量必須在定義任意游標(biāo)或句柄之前定義,而句柄必須在游標(biāo)之后定義(例如上面done語句)。不遵守此順序?qū)a(chǎn)生錯(cuò)誤消息。
執(zhí)行該存儲(chǔ)過程,它將定義幾個(gè)變量和一個(gè)continue handler,定義并打開一個(gè)游標(biāo),重復(fù)讀取所有行,在fetch語句之后,循環(huán)結(jié)束之前可以在循環(huán)內(nèi)放入任意需要的處理,例如向臨時(shí)表中插入數(shù)據(jù),查詢某變量的值等。
上述示例,在打開游標(biāo)之前創(chuàng)建了一個(gè)臨時(shí)表:emp_dempart_temp,在遍歷游標(biāo)查詢結(jié)果時(shí),在滿足done != 1的條件下向該表插入 存儲(chǔ)過程中游標(biāo)查詢生成的結(jié)果。
調(diào)用存儲(chǔ)過程:
CALL empIndepart_list(2);
使用select語句查看emp_dempart_temp的內(nèi)容:
select * from emp_dempart_temp;
