1. 程式人生 > >MySQL遊標的簡單實踐

MySQL遊標的簡單實踐

bool 其余 bsp number 沒有 close 需要 簡單 取出

Q:為什麽要使用遊標?

A:

  在存儲過程(或函數)中,如果某條select語句返回的結果集中只有1行,可以使用select into語句(上幾篇博客有介紹到用法)來得到該行進行處理;如果結果集中有多行,簡單的select語句成批地進行處理,需要在檢索出來的行中前進或後退一行或多行……若是想得到其中的每一行進行處理,就必須使用遊標。

Q:什麽是遊標?

A:

  遊標(cursor),是一個存儲在MySQL服務器上的數據庫查詢,遊標不是一條 SELECT語句,而是被該語句檢索出來的結果集;可以看做是指向查詢結果集的指針;通過cursor,就可以一次一行的從結果集中把行拿出來處理。

註意:MySQL遊標只能用於存儲過程和函數。

遊標的處理過程:4步

  ①聲明遊標declare:沒有檢索數據,只是定義要使用的select語句

  ②打開遊標open:打開遊標以供使用,用上一步定義的select語句把數據實際檢索出來

  ③檢索遊標fetch:對於填有數據的遊標,根據需要取出(檢索)各行

  ④關閉遊標close:在結束遊標使用時,必須關閉遊標

1、聲明遊標

DECLARE cursor_name CURSOR FOR select_statement;

聲明一個遊標cursor_name,讓其指向查詢select_statement的結果集。

註意:

  ①遊標聲明必須出現在變量和條件聲明的後面,但是在異常處理聲明的前面

  ②一個過程中可以有多個遊標聲明

2、打開遊標

OPEN cursor_name;

cursor_name是聲明中定義的名字;打開遊標時才執行相應的select_statement。

3、檢索遊標

FETCH cursor_name INTO var_name [, var_name] ...

從遊標cursor_name中拿出一行,把該行的各個列值保存到各個變量中。

解析:

  一次只拿一行,拿完後,自動移動指針到下一行;

  如果沒有拿到行,會拋出異常,其SQLSTATE代碼值為‘02000’,此時要檢測到該情況,需要聲明異常處理程序 (針對條件NOT FOUND也可以),通常需要在一個循環中來執行fetch語句,通過檢測以上異常來結束循環。

4、關閉遊標

CLOSE cursor_name;

收回遊標占用的內存,別浪費資源嘛。

例1:創建過程,計算players表中行的數量

技術分享
mysql> delimiter $$
mysql> create procedure number_of_players(
    ->   out pnumber int)
    -> begin
    ->   declare a_playerno int;  
    ->   declare found bool default true;  循環控制變量,其值為false時循環結束   
    ->
    ->   declare c_players cursor for
    ->     select playerno from PLAYERS;  ①聲明遊標
    ->
    ->   declare continue handler for not found
    ->     set found=false;  聲明異常處理程序
    ->
    ->   set pnumber=0;
    ->
    ->   open c_players;  ②打開遊標
    ->
    ->   fetch c_players into a_playerno;  ③檢索遊標(檢索第一行)
    ->   while found do
    ->     set pnumber=pnumber+1;
    ->     fetch c_players into a_playerno;
    ->   end while;  循環檢索其余行
    ->
    ->   close c_players;  ④關閉遊標
    -> end$$
mysql> delimiter ;
mysql> call number_of_players(@pnumber);
mysql> select @pnumber;
+----------+
| @pnumber |
+----------+
|       14 |
+----------+
mysql> select count(*) from PLAYERS;
+----------+
| count(*) |
+----------+
|       14 |
+----------+
技術分享

例2:創建過程,計算某個球員的罰款次數--遊標聲明中可以包含變量

技術分享
mysql> delimiter $$
mysql> create procedure number_penalties(
    ->   in p_playerno int,
    ->   out pnumber int)
    -> begin
    ->   declare a_playerno int;
    ->   declare found bool default true;  循環控制變量
    -> 
    ->   declare c_players cursor for  聲明遊標
    ->     select playerno
    ->     from PENALTIES
    ->     where playerno = p_playerno;  包含變量p_playerno
    -> 
    ->   declare continue handler for not found
    ->     set found=false;  聲明異常處理程序
    -> 
    ->   set pnumber=0;
    ->  
    ->   open c_players;  打開遊標
    -> 
    ->   fetch c_players into a_playerno;
    ->   while found do    循環檢索遊標每一行
    ->     set pnumber=pnumber+1;
    ->     fetch c_players into a_playerno;
    ->   end while;
    ->
    ->   close c_players;  關閉遊標
    -> end$$
mysql> delimiter ;
mysql> call number_penalties(44,@pnumber);
mysql> select @pnumber;
+----------+
| @pnumber |
+----------+
|        3 |
+----------+

MySQL遊標的簡單實踐