1. 程式人生 > 資料庫 >MySQL遊標概念與用法詳解

MySQL遊標概念與用法詳解

本文例項講述了MySQL遊標概念與用法。分享給大家供大家參考,具體如下:

1、遊標的概念(Cursor)

一條sql,對應N條資源,取出資源的介面,就是遊標,沿著遊標,可以一次取出1行。如果開發過安卓的同學應該知道有一個Api是Cursor,也是讀取SQLite資料庫用的,和這個有點類似。

2、使用遊標的步驟

(1)宣告

使用declare進行宣告

declare 遊標名 cursor for select_statement

(2)開啟遊標

使用open進行開啟

open 遊標名

(3)從遊標中取值

使用fetch進行取值

fetch 遊標名 into var1,var2[,...] --將取到的一行賦值給多個變數

(4)關閉遊標

使用close關閉遊標

close 遊標名

3、建立一個簡單的遊標

需求:從商品表中讀取第一行資料

商品表(goods)資料:

這裡寫圖片描述

注意:我這裡已經將MySQL的結束識別符號改為 $,如果要知道怎麼設定為$,請參考前面一篇文章:MySQL觸發器。

定義:

create procedure p12()
begin
  /*定義三個變數用於存放商品id,商品名稱,商品庫存量*/
  declare row_gid int ; 
  declare row_name varchar(20);
  declare row_num int;
  declare getgoods cursor for select gid,name,num from goods;  --定義遊標
  open getgoods; --開啟遊標
  fetch getgoods into row_gid,row_name,row_num;--從遊標中取值
  select row_name,row_num; --顯示操作
  close getgoods; --關閉遊標
end$

輸出結果:

這裡寫圖片描述

4、多次取值操作

create procedure p13()
begin
  declare row_gid int ;
  declare row_name varchar(20);
  declare row_num int;
  declare getgoods cursor for select gid,num from goods;  
  open getgoods;
  fetch getgoods into row_gid,row_num;
  select row_name,row_num;
  fetch getgoods into row_gid,row_num;
  close getgoods;
end$

輸出:

這裡寫圖片描述

注意:當遊標讀到末尾,如果繼續進行取值操作會發生報錯

5、遊標迴圈表中的所有資料

(1)使用計數器來迴圈

create procedure p14()
begin 
  declare cnt int default 0;
  declare i int default 0;
  declare row_gid int ;
  declare row_name varchar(20);
  declare row_num int;
  declare getgoods cursor for select gid,num from goods;
  select count(*) into cnt from goods;
  open getgoods;
  repeat 
    fetch getgoods into row_gid,row_num;
  set i:= i+1;
  until i >= cnt end repeat;
  close getgoods;
end$

輸出結果:

這裡寫圖片描述

(2)使用越界標誌來控制迴圈

在mysql cursor中,可以宣告declare continue handler來操作1個越界標誌

語法:

declare continue handler for NOT FOUND statement;

使用:

create procedure p15()
begin
  declare row_gid int ;
  declare row_name varchar(20);
  declare row_num int;
  declare have int default 1;
  declare getgoods cursor for select gid,num from goods;
  declare continue handler for NOT FOUND set have:= 0;
  open getgoods;
  repeat 
    fetch getgoods into row_gid,row_num;
  until have = 0 end repeat;
  close getgoods;
end$

輸出結果:

這裡寫圖片描述

注意:這裡發生了錯誤,這裡輸出了4行資料,而表中只有3行資料,而且還爆出了警告,後面會說怎麼結果這個問題。

程式執行邏輯:

循環遊標->fetch第三條資料->顯示->fetch第四條資料->沒有資料->設定have=0操作->執行continue Handler->程式不退出,執行顯示操作->還是顯示第三條資料

6、continue和exit的區別

continue:若沒有資料返回,程式繼續,並將變數IS_FOUND設為0,這種情況是出現在select XX into XXX from tablename的時候發生的。
exit:若沒有資料返回,退出程式,並將變數IS_FOUND設為0,這種情況是出現在select XX into XXX from tablename的時候發生的。

使用exit來替換continue:
使用exit就不會出現上面的那種情況了,程式執行邏輯:

循環遊標->fetch到第三條資料->顯示->第四次fetch操作->沒有資料->設定 have=0操作->程式直接退出exit

所以就沒有顯示出第四條資料。

create procedure p16()
begin
  declare row_gid int ;
  declare row_name varchar(20);
  declare row_num int;
  declare have int default 1;
  declare getgoods cursor for select gid,num from goods;
  declare exit handler for NOT FOUND set have:= 0;
  open getgoods;
  repeat 
    fetch getgoods into row_gid,row_num;
  until have = 0 end repeat;
  close getgoods;
end$

輸出結果:

這裡寫圖片描述

7、正確的遊標迴圈

在一些特殊的情況中,我們可以讀到的資料為空,或者壓根sql語句就有錯誤,我們不能避免出現這種情況,所以我們要正確的使用遊標迴圈操作。

首先應該建立遊標,然後開啟遊標後,應先手動進行fetch操作獲取到一行資料,然後再通過迴圈,在迴圈裡先做處理內容,後進行fetch操作。這樣如果在手動獲取資料的期間就沒有獲得到資料的話,就會執行have = 0,如果是repeat迴圈,然後進入repeat迴圈,先輸出null資料,最後又進行獲取,這樣執行到until時就會退出迴圈;如果是while迴圈,壓根就不進去while迴圈裡,就不會有任何1行輸出。

(1)repeat迴圈:

create procedure p17()
begin
  declare row_gid int;
  declare row_name varchar(20);
  declare row_num int;
  declare have int default 1;
  declare getgoods cursor for select gid,num from goods where 0;
  declare continue handler for NOT FOUND set have:= 0;
  open getgoods;
  fetch getgoods into row_gid,row_num;
  repeat 
  select row_name,row_num;
    fetch getgoods into row_gid,row_num;
  until have = 0 end repeat;
  close getgoods;
end$

輸出結果:

這裡寫圖片描述

(2)while迴圈:

create procedure p18()
begin
  declare row_gid int;
  declare row_name varchar(20);
  declare row_num int;
  declare have int default 1;
  declare getgoods cursor for select gid,row_num;
  while have = 1 do 
  select row_name,row_num;
  end while;
  close getgoods;
end$

輸出結果:

這裡寫圖片描述

更多關於MySQL相關內容感興趣的讀者可檢視本站專題:《MySQL查詢技巧大全》、《MySQL事務操作技巧彙總》、《MySQL儲存過程技巧大全》、《MySQL資料庫鎖相關技巧彙總》及《MySQL常用函式大彙總》

希望本文所述對大家MySQL資料庫計有所幫助。