在mysql中,遊標有指標的作用,主要用於對查詢資料庫所傳回的記錄結果集進行遍歷,以便進行對應的操作。遊標實際上是一種能從包含多個資料記錄的結果集中每次提取一筆記錄的機制。關聯式資料庫管理系統實質是面向集合的,在MySQL中並沒有一種描述表中單一記錄的表達形式,除非使用WHERE子句來限制只有一筆記錄被選取;所以有時必須藉助於遊標來進行單一記錄的數據處理。
本教學操作環境:windows7系統、mysql8版本、Dell G3電腦。
MySQL遊標(Cursor)
# 遊標其實是一種能從包含多筆資料記錄的結果集中每次提取一筆記錄的機制。
遊標充當指標的作用。
儘管遊標能遍歷結果中的所有行,但他一次只指向一行。
遊標的作用就是用來對查詢資料庫所傳回的記錄進行遍歷,以便進行對應的操作。
關聯式資料庫管理系統實質是面向集合的,在 MySQL 中並沒有一種描述表中單一記錄的表達形式,除非使用 WHERE 子句來限制只有一筆記錄被選取。所以有時我們必須藉助於遊標來進行單一記錄的資料處理。
一般透過遊標定位到結果集的某一行進行資料修改。
遊標的用法
1、宣告一個遊標:declare 遊標名稱CURSOR for table;
(這裡的table可以是你查詢出來的任一集合)
2、開啟定義的遊標:open 遊標名稱;
3、取得下一行資料:FETCH 遊標名稱into testrangeid,versionid;
4、需要執行的語句(增刪改查):這裡視具體情況而定
5、釋放遊標:CLOSE 遊標名稱;
注:mysql預存程序每一句後面必須用;結尾,使用的暫存欄位需要在定義遊標之前進行宣告。
實例
- BEGIN --定义变量 declare testrangeid BIGINT; declare versionid BIGINT; declare done int; --创建游标,并存储数据 declare cur_test CURSOR for select id as testrangeid,version_id as versionid from tp_testrange; --游标中的内容执行完后将done设置为1 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; --打开游标 open cur_test; --执行循环 posLoop:LOOP --判断是否结束循环 IF done=1 THEN LEAVE posLoop; END IF; --取游标中的值 FETCH cur_test into testrangeid,versionid; --执行更新操作 update tp_data_execute set version_id=versionid where testrange_id = testrangeid; END LOOP posLoop; --释放游标 CLOSE cur_test; END -
範例2:
我們現在要用預存程序做一個功能,統計iphone的總庫存是多少,並把總數輸出到控制台。
--在windows系统中写存储过程时,如果需要使用declare声明变量,需要添加这个关键字,否则会报错。 delimiter // drop procedure if exists StatisticStore; CREATE PROCEDURE StatisticStore() BEGIN --创建接收游标数据的变量 declare c int; declare n varchar(20); --创建总数变量 declare total int default 0; --创建结束标志变量 declare done int default false; --创建游标 declare cur cursor for select name,count from store where name = 'iphone'; --指定游标循环结束时的返回值 declare continue HANDLER for not found set done = true; --设置初始值 set total = 0; --打开游标 open cur; --开始循环游标里的数据 read_loop:loop --根据游标当前指向的一条数据 fetch cur into n,c; --判断游标的循环是否结束 if done then leave read_loop; --跳出游标循环 end if; --获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作, set total = total + c; --结束游标循环 end loop; --关闭游标 close cur; --输出结果 select total; END; --调用存储过程 call StatisticStore();
fetch是取得遊標目前指向的資料行,並將指標指向下一行,當遊標已經指向最後一行時繼續執行會造成遊標溢位。
使用loop循環遊標時,他本身是不會監控是否到最後一條資料了,像下面程式碼這種寫法,就會造成死循環;
read_loop:loop fetch cur into n,c; set total = total+c; end loop;
在MySql中,造成遊標溢出時會引發mysql預先定義的NOT FOUND錯誤,所以在上面使用下面的程式碼指定了當引發not found錯誤時定義一個continue 的事件,並指定這個事件發生時修改done變數的值。
declare continue HANDLER for not found set done = true;
所以在迴圈時加上了下面這句程式碼:
--判断游标的循环是否结束 if done then leave read_loop; --跳出游标循环 end if;
如果done的值是true,就結束迴圈。繼續執行下面的程式碼
使用方式
遊標有三種使用方式:
第一種就是上面的實現,使用loop循環;
第二種方式如下,使用while迴圈:
drop procedure if exists StatisticStore1; CREATE PROCEDURE StatisticStore1() BEGIN declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; fetch cur into n,c; while(not done) do set total = total + c; fetch cur into n,c; end while; close cur; select total; END; call StatisticStore1();
第三種方式是使用repeat執行:
drop procedure if exists StatisticStore2; CREATE PROCEDURE StatisticStore2() BEGIN declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; repeat fetch cur into n,c; if not done then set total = total + c; end if; until done end repeat; close cur; select total; END; call StatisticStore2();
遊標嵌套
在mysql中,每個begin end 區塊都是一個獨立的scope區域,由於MySql中同一個error的事件只能定義一次,如果多定義的話在編譯時會提示Duplicate handler declared in the same block。
drop procedure if exists StatisticStore3; CREATE PROCEDURE StatisticStore3() BEGIN declare _n varchar(20); declare done int default false; declare cur cursor for select name from store group by name; declare continue HANDLER for not found set done = true; open cur; read_loop:loop fetch cur into _n; if done then leave read_loop; end if; begin declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; iphone_loop:loop fetch cur into n,c; if done then leave iphone_loop; end if; set total = total + c; end loop; close cur; select _n,n,total; end; begin declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'android'; declare continue HANDLER for not found set done = true; set total = 0; open cur; android_loop:loop fetch cur into n,c; if done then leave android_loop; end if; set total = total + c; end loop; close cur; select _n,n,total; end; begin end; end loop; close cur; END; call StatisticStore3();
上面就是實作一個巢狀循環,當然這個例子比較牽強。湊合看看就行。
動態SQL
Mysql 支援動態SQL的功能
set @sqlStr='select * from table where condition1 = ?'; prepare s1 for @sqlStr; --如果有多个参数用逗号分隔 execute s1 using @condition1; --手工释放,或者是 connection 关闭时, server 自动回收 deallocate prepare s1;
【相關推薦:mysql影片教學】
以上是mysql遊標有什麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!