1. 程式人生 > >MySQL遊標簡析

MySQL遊標簡析

Notes:SQL檔案

遊標的概念

遊標(cursor)是一個儲存在MySQL伺服器上的資料庫查詢,它不是一條SELECT語句,而是被該語句檢索出來的結果集。在儲存了遊標之後,應用程式可以根據需要滾動或瀏覽其中的資料。
遊標主要用於互動式應用,其中使用者需要滾動螢幕上的資料,並對資料進行瀏覽或做出更改。
MySQL的遊標只能用於儲存過程(和函式)。

使用遊標

  • 在能夠使用遊標前,必須宣告(定義)它。這個過程實際上沒有檢索資料,它只是定義要使用的SELECT語句。
  • 一旦宣告以後,必須開啟遊標以供使用。這個過程用前面定義的SELECT語句把資料檢索出來。
  • 對於填有資料的遊標,根據需要取出(檢索)各行。
  • 在結束遊標的使用時,必須關閉遊標。

建立遊標

DECLARE命名遊標,並定義相應的SELECT語句,根據需要帶WHERE和其他的子句。
SQL:

CREATE PROCEDURE processorders()
BEGIN
   DECLARE ordernumbers CURSOR
   FOR SELECT order_num FROM orders;
   -- 開啟遊標
   OPEN ordernumbers;
   -- 關閉遊標
   CLOSE ordernumbers;
END;

解析:

這個儲存過程並沒有做很多事情,DECLARE語句用來定義和命名遊標,這裡為ordernumbers。儲存過程完成後,遊標就消失(因為它侷限於儲存過程)。

開啟和關閉遊標

開啟遊標:

OPEN ordernumbers;

關閉遊標:

CLOSE ordernumbers;

注意:CLOSE釋放遊標使用的所有內部記憶體和資源,因此在每個遊標不再需要時都應該關閉。
在一個遊標關閉後,如果沒有重新開啟,則不能使用它。但是,使用宣告過的遊標不需要再次宣告,用OPEN語句開啟就可以了。
如果你不明確關閉遊標,MySQL將會在到達END語句時自動關閉它。也即是隱含關閉

使用遊標資料

FETCH語句:在一個遊標被開啟後,可以使用FETCH語句分別訪問它的每一行。FETCH指定檢索什麼資料(所需的列),檢索出來的資料儲存在什麼地方。它還向前移動遊標中的內部行指標,使下一條FETCH

語句檢索下一行(不重複讀取同一行)。

遊標檢索單個行

建立:

CREATE PROCEDURE processorders(
   OUT ototal DECIMAL(8,2)
)
BEGIN
   DECLARE o INT;
   DECLARE ordernumbers CURSOR
   FOR SELECT order_num FROM orders;
   -- 開啟遊標
   OPEN ordernumbers;

   FETCH ordernumbers INTO o;

   SELECT o INTO ototal;
   -- 關閉遊標
   CLOSE ordernumbers;
END;

呼叫:

CALL processorders(@p1);

結果:

SELECT @p1;
-- 20005
遊標迴圈檢索資料

建立:

CREATE PROCEDURE processorders( 
   OUT ototal DECIMAL(8,2)
)
BEGIN
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;

   DECLARE ordernumbers CURSOR
   FOR SELECT order_num FROM orders;

   -- 定義一個CONTINUE HANDLER,SQLSTATE '02000'是一個未找到條件,當REPEAT由於沒有更多的行供迴圈而不能繼續時
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 

   -- 開啟遊標
   OPEN ordernumbers;
   -- 迴圈開始
   REPEAT 
     FETCH ordernumbers INTO o;
   -- 迴圈結束
   UNTIL done END REPEAT;
   SELECT o INTO ototal;
   -- 關閉遊標
   CLOSE ordernumbers;
END;

呼叫:

CALL processorders(@p1);

結果:

SELECT @p1;
-- 20008
綜合遊標示例

建立:

CREATE PROCEDURE processorders()
BEGIN
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;
   DECLARE t DECIMAL(8,2);

   -- 定義遊標
   DECLARE ordernumbers CURSOR
   FOR SELECT order_num FROM orders;

   -- 定義一個CONTINUE HANDLER,SQLSTATE '02000'是一個未找到條件,當REPEAT由於沒有更多的行供迴圈而不能繼續時
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 

   -- 建立表格存放資料
   CREATE TABLE IF NOT EXISTS ordertotals(
         order_num INT COMMENT '訂單號碼',
         total DECIMAL(8,2) COMMENT '總計'
   );

   -- 開啟遊標
   OPEN ordernumbers;
   -- 迴圈開始
   REPEAT 
     FETCH ordernumbers INTO o;
     -- 呼叫儲存過程
     CALL ordertoatal(o,1,t);
     -- 往ordertotals表中插入資料
     INSERT INTO ordertotals(order_num,total)VALUES(o,t);
   -- 迴圈結束
   UNTIL done END REPEAT;

   -- 關閉遊標
   CLOSE ordernumbers;
END;

呼叫:

CALL processorders();
SELECT * FROM ordertotals;

結果

order_num toatal
20005 158.86
20009 40.78
20006 58.30
20007 1060.00
20008 132.50
20008 132.50