mysql遊標有什麼用

2022-06-27 14:02:36

在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遊標有什麼用的詳細內容,更多請關注TW511.COM其它相關文章!