MySQL 游標
游標的特性
-
不敏感:數據庫可以選擇不復制結果集
-
只讀
-
不滾動:游標只能向一方向前進,並且不可以跳過任何一行數據
游標的優點
-
游標是針對行操作的,對從數據庫中 select 查詢得到的結果集的 每一行可以
進行分開的獨立的相同或者不相同的操作,是一種分離的思想。
游標的缺點
-
性能不高
-
只能一行一行操作
-
使用游標會產生死鎖,造成內存開銷大
游標的適用場景
-
存儲過程
-
函數
-
觸發器
-
事件
游標的操作
1、游標的定義
DECLARE 光標名稱 CURSOR FOR 查詢語法
declare cursor_name cursor for select_statement
2、打開游標
OPEN 光標名稱
open cursor_name
3、取游標中的數據
FETCH 光標名稱 INFO var_name [,var_name ].....
fetch cursor_name info var_name
4、關閉游標
CLOSE curso_name;
close 光標名稱
5、釋放游標
DEALLOCATE 光標名稱
deallocate cursor_name;
游標示例
create table student( stuId int primary key auto_increment, stuName varchar(20), stuSex varchar(2), stuAge int )default charset=utf8; insert into student(stuName,stuSex,stuAge) values ('小明','男',20), ('小花','女',19), ('大赤','男',20), ('可樂','男',19), ('瑩瑩','女',19);
普通案例
delimiter //
create procedure p1()
begin
declare id int;
declare name varchar(100) character set utf8;
declare done int default 0;
-- 聲明游標
declare mc cursor for select stuId,stuName from student where stuAge >19;
declare continue handler for not found set done = 1;
-- 打開游標
open mc;
-- 獲取結果
fetch mc into id,name;
-- 這里是為了顯示獲取結果
select id,name;
-- 關閉游標
close mc;
end //
delimiter ;
試使用 三種方式 使用游標創建一個存儲過程,統計年齡大於19的記錄的數量
Loop循環
-- 定義語法結束符號
delimiter //
-- 創建一個 名稱為 p2 的存儲過程
create procedure p2()
begin
-- 創建 用於接收游標值的變量
declare id,age,total int;
-- 注意 接收游標值為中文時 需要 給變量 指定 字符集為utf8
declare name,sex varchar(20) character set utf8;
-- 游標結束的標志
declare done int default 0;
-- 聲明游標
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游標循環結束時的返回值
declare continue handler for not found set done =1;
-- 打開游標
open cur;
-- 初始化 變量
set total = 0;
-- loop 循環
xxx:loop
-- 根據游標當前指向的一條數據
fetch cur into id,name,sex,age;
-- 當 游標的返回值為 1 時 退出 loop循環
if done = 1 then
leave xxx;
end if;
-- 累計
set total = total + 1;
end loop;
-- 關閉游標
close cur;
-- 輸出 累計的結果
select total;
end //
delimiter ;
while 循delimiter /-- 創建一個 名稱為 p3 的存儲過程create procedure p3()
delimiter //
-- 創建一個 名稱為 p3 的存儲過程
create procedure p3()
begin
-- 創建 用於接收游標值的變量
declare id,age,total int;
-- 注意 接收游標值為中文時 需要 給變量 指定 字符集為utf8
declare name,sex varchar(20) character set utf8;
-- 游標結束的標志
declare done int default 0;
-- 聲明游標
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游標循環結束時的返回值
declare continue handler for not found set done = 1;
-- 打開游標
open cur;
-- 初始化 變量
set total = 0;
-- while 循環
while done != 1 do
fetch cur into id,name,sex,age;
if done != 1 then
set total = total + 1;
end if;
end while;
-- 關閉游標
close cur;
-- 輸出 累計的結果
select total;
end //
delimiter ;
repeat 循環
delimiter //
-- 創建一個 名稱為 p3 的存儲過程
create procedure p3()
begin
-- 創建 用於接收游標值的變量
declare id,age,total int;
-- 注意 接收游標值為中文時 需要 給變量 指定 字符集為utf8
declare name,sex varchar(20) character set utf8;
-- 游標結束的標志
declare done int default 0;
-- 聲明游標
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游標循環結束時的返回值
declare continue handler for not found set done = 1;
-- 打開游標
open cur;
-- 初始化 變量
set total = 0;
-- repeat 循環
repeat
fetch cur into id,name,sex,age;
if done != 1 then
set total = total + 1;
end if;
until done = 1
end repeat;
-- 關閉游標
close cur;
-- 輸出 累計的結果
select total;
end //
delimiter ;
while 循環 repeat 循環 不知道 是不是理解錯了 會多循環一次…(還是游標多走了一次…) ----> 進行累加計算時,先判斷游標的結束標志(done) 是否是為1