Mysql儲存過程中使用多遊標
阿新 • • 發佈:2019-02-17
mysql
的儲存過程可以很方便使用遊標來實現一些功能,儲存過程的寫法大致如下:
先建立一張表,插入一些測試資料:
DROP TABLE IF EXISTS netingcn_proc_test;
CREATE TABLE `netingcn_proc_test` (
`id` INTEGER(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20),
`password` VARCHAR(20),
PRIMARY KEY (`id`)
)ENGINE=InnoDB;
insert into netingcn_proc_test(name, password) values
('procedure1', 'pass1'),
('procedure2', 'pass2'),
('procedure3', 'pass3'),
('procedure4', 'pass4');
下面就是一個簡單儲存過程的例子:
drop procedure IF EXISTS test_proc;
delimiter //
create procedure test_proc()
begin
-- 宣告一個標誌done, 用來判斷遊標是否遍歷完成
DECLARE done INT DEFAULT 0;
-- 宣告一個變數,用來存放從遊標中提取的資料
-- 特別注意這裡的名字不能與由遊標中使用的列明相同,否則得到的資料都是NULL
DECLARE tname varchar(50 ) DEFAULT NULL;
DECLARE tpass varchar(50) DEFAULT NULL;
-- 宣告遊標對應的 SQL 語句
DECLARE cur CURSOR FOR
select name, password from netingcn_proc_test;
-- 在遊標迴圈到最後會將 done 設定為 1
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- 執行查詢
open cur;
-- 遍歷遊標每一行
REPEAT
-- 把一行的資訊存放在對應的變數中
FETCH cur INTO tname, tpass;
if not done then
-- 這裡就可以使用 tname, tpass 對應的資訊了
select tname, tpass;
end if;
UNTIL done END REPEAT;
CLOSE cur;
end
//
delimiter ;
-- 執行儲存過程
call test_proc();
需要注意的是變數的宣告、遊標的宣告和HANDLER
宣告的順序不能搞錯,必須是先宣告變數,再申明遊標,最後宣告HANDLER
。上述儲存過程的例子中只使用了一個遊標,那麼如果要使用兩個或者更多遊標怎麼辦,其實很簡單,可以這麼說,一個怎麼用兩個就是怎麼用的。例子如下:
drop procedure IF EXISTS test_proc_1;
delimiter //
create procedure test_proc_1()
begin
DECLARE done INT DEFAULT 0;
DECLARE tid int(11) DEFAULT 0;
DECLARE tname varchar(50) DEFAULT NULL;
DECLARE tpass varchar(50) DEFAULT NULL;
DECLARE cur_1 CURSOR FOR
select name, password from netingcn_proc_test;
DECLARE cur_2 CURSOR FOR
select id, name from netingcn_proc_test;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur_1;
REPEAT
FETCH cur_1 INTO tname, tpass;
if not done then
select tname, tpass;
end if;
UNTIL done END REPEAT;
CLOSE cur_1;
-- 注意這裡,一定要重置done的值為 0
set done = 0;
open cur_2;
REPEAT
FETCH cur_2 INTO tid, tname;
if not done then
select tid, tname;
end if;
UNTIL done END REPEAT;
CLOSE cur_2;
end
//
delimiter ;
call test_proc_1();
上述程式碼和第一個例子中基本一樣,就是多了一個遊標宣告和遍歷遊標。這裡需要注意的是,在遍歷第二個遊標前使用了set done = 0
,因為當第一個遊標遍歷玩後其值被handler
設定為1
了,如果不用set
把它設定為 0
,那麼第二個遊標就不會遍歷了。當然好習慣是在每個開啟遊標的操作前都用該語句,確保遊標能真正遍歷。當然還可以使用begin
語句塊巢狀的方式來處理多個遊標,例如:
drop procedure IF EXISTS test_proc_2;
delimiter //
create procedure test_proc_2()
begin
DECLARE done INT DEFAULT 0;
DECLARE tname varchar(50) DEFAULT NULL;
DECLARE tpass varchar(50) DEFAULT NULL;
DECLARE cur_1 CURSOR FOR
select name, password from netingcn_proc_test;
DECLARE cur_2 CURSOR FOR
select id, name from netingcn_proc_test;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur_1;
REPEAT
FETCH cur_1 INTO tname, tpass;
if not done then
select tname, tpass;
end if;
UNTIL done END REPEAT;
CLOSE cur_1;
begin
DECLARE done INT DEFAULT 0;
DECLARE tid int(11) DEFAULT 0;
DECLARE tname varchar(50) DEFAULT NULL;
DECLARE cur_2 CURSOR FOR
select id, name from netingcn_proc_test;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur_2;
REPEAT
FETCH cur_2 INTO tid, tname;
if not done then
select tid, tname;
end if;
UNTIL done END REPEAT;
CLOSE cur_2;
end;
end
//
delimiter ;
call test_proc_2();