游標cursor
MySQL檢索操作返回一組稱為結果集的行。這組返回的行都是與SQL語句相匹配的零或多
行。簡單的SELECT語句沒辦法得到第一行、下一行或前10行,也不存在每次一行的處理
所有行的簡單方法,即批量處理行。
故要檢索出來的行中前進或后退一或多行時,可以用游標。
游標是一個存儲在MySQL服務器上的數據庫查詢,不是一條SELECT語句,而是被該語句
檢索出來的結果集。在存儲了游標后,應用程序可以根據需要滾動或瀏覽其中的數據。
主要用於交互式應用,其中用戶需要滾動屏幕上的數據,並對數據進行瀏覽或做出更改
只能用於存儲過程,MySQL游標只能用於存儲過程和函數
使用游標
- 使用前,先聲明游標,這一過程實際上沒有檢索數據,只是定義要使用的SELECT語句
- 一旦聲明后,必須打開游標以供使用,這個過程用前面定義的SELECT語句把數據實際檢
- 索出來
- 對於填有數據的游標,根據需要檢索各行
- 結束游標使用時,要關閉游標
創建游標
DECLARE命名創建游標,並定義相應的SELECT語句,根據需要,帶WHERE和其他語句
例一,定義ordernumbers游標,檢索所有訂單的SELECT語句
1 CREATE PROCEDURE processorders() 2 BEGIN 3 DECLARE ordernumbers CURSOR 4 FOR 5 SELECT order_num FROM orders; 6 END;

DECLARE語句用來定義命名游標ordernumbers
存儲過程處理完后,游標消失,因為游標僅局限於存儲過程
打開和關閉游標
1 OPEN ordernumbers;
在處理OPEN語句時執行查詢,存儲檢索出的數據以供瀏覽和滾動。
1 CLOSE ordernumbers;
CLOSE釋放游標使用道德所有內部內存和資源,因此在每個游標不再需要時都應該關閉。
游標關閉后,若沒有重新打開,則不能再使用,但使用聲明過的游標不需要再次聲明,用
OPEN語句打開即可。
如果不明確關閉游標,MySQL將在到達END語句時自動關閉。
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare the cursor 4 DECLARE ordernumbers CURSOR 5 FOR 6 SELECT order_num FROM orders; 7 8 -- OPEN the cursor 9 OPEN ordernumbers; 10 11 -- CLOSE the cursor 12 CLOSE ordernumbers; 13 END;
使用游標
游標被打開后,使用FETCH語句分別訪問它的每一行。FETCH指定檢索什么數據,檢索
出來的數據存儲在什么地方。游標還向前移動游標中的內部行指針,使下一條FETCH語句
檢索下一行(不重復讀取同一行)
例二、從游標中檢索單個行:
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLARE o INT; 5 6 -- Declare the cursor 7 DECLARE ordernumbers CURSOR 8 FOR 9 SELECT order_num FROM orders; 10 11 -- Open the cursor 12 OPEN ordernumbers; 13 14 -- Get order number 15 FETCH ordernumbers INTO o; 16 17 -- Close the cursor 18 CLOSE ordernumbers; 19 END;
其中FETCH用來檢索當前行的order_num列,自動從第一行開始,到一個名為o的局部聲明的變量中,檢索出的數據不做處理。
例三、循環檢索數據,從第一行到最后一行:
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLAE done BOOLEAN DEFAULT 0; 5 DECLARE o INT; 6 7 -- Declare the cursor 8 DECLARE ordernumbers CURSOR 9 FOR 10 SELECT order_num FROM orders; 11 12 -- Declare continue handler 13 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 14 15 -- Open the cursor 16 OPEN ordernumbers; 17 18 --loop through all rows 19 REPEAT 20 21 -- Get order number 22 FETCH ordernumbers INTO o; 23 24 -- End of loop 25 UNTIL done END REPEAT; 26 27 -- Close the cursor 28 CLOSE ordernumbers; 29 END;
使用FETCH檢索當前order_num到聲明的名為o的變量中,但與例一不同在於,FETCH是在REPEAT內,因此它反復執行知道done為真(DECLAE done BOOLEAN DEFAULT 0;)(UNTIL done END REPEAT;)
當(DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;)時done為真
這里定義了一個CONTINUE HANDLER,即條件出現時被執行的代碼,當SQLSTATE '02000'出現時,done為1
SQLSTATE '02000'是一個未找到條件,當REPEAT循環完沒法繼續時,出現這個條件
如果調用這個存儲過程,他將定義幾個變量和一個CONTINUE HANDLER,定義並打開一個游標,重復讀取所有行,然后關閉游標。
例四、對取出的數據進行
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLARE done BOOLEAN DEFAULT 0; 5 DECLARE o INT; 6 DECLARE t DECIMAL(8,2); 7 8 -- Declare the cursor 9 DECLARE ordernumbers CURSOR 10 FOR 11 SELECT order_num FROM orders; 12 -- Declare continue handler 13 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 14 15 -- Create a table to store the results 16 CREATE TABLE IF NOT EXISTS ordertotals 17 (order_num INT, total DECIMAL(8,2)); 18 19 -- Open the cursor 20 OPEN ordernumbers; 21 22 --loop through all rows 23 REPEAT 24 25 -- Get order number 26 FETCH ordernumbers INTO o; 27 28 --Get the total for this order 29 CALL ordertotal(o,1,t); 30 31 -- Insert order and total into ordertotals 32 INSERT INTO ordertotals(order_num,total) 33 VALUES(o,t); 34 35 -- End of loop 36 UNTIL done END REPEAT; 37 38 -- Close the cursor 39 CLOSE ordernumbers; 40 END;
增加變量t存儲每個訂單的合計。此存儲過程還在運行中創建了一個新表(CREATE TABLE IF NOT EXISTS ordertotals),這個表將保存存儲過程生成的結果。
FETCH取每個order_num,然后用CALL執行另一個存儲過程來計算每個訂單的帶稅的合計,結果存儲到t。
最后用INSERT保存每個訂單的訂單號和合計。
可以用SELECT語句查看此存儲過程創建的表
1 SELECT* FROM ordertotals;