摘要: 本篇博客僅做爲筆記,若有侵權,請聯繫,當即刪除(網上找博客學習,而後手記筆記,因紙質筆記不便保存,因此保存到網絡筆記)。數據庫
本博客將講授什麼是遊標以及如何使用遊標。瀏覽器
1、遊標服務器
注意:須要MySQL 5 MySQL5添加了對遊標的支持,所以,本博客內容適用於MySQL 5以及之後的版本。網絡
由前面博客能夠知道,MySQL檢索操做返回一組稱爲結果集的行。這組返回的行都是與SQL語句相匹配的行(零行或多行)。使用簡單的SELECT語句,例如,沒有辦法獲得第一行、下一行或前10行,也不存在每次一行地處理全部行的簡單方法(相對於成批地處理它們)。函數
有時,須要檢索出來的行中前進或後退一行或多行。這就是使用遊標的緣由。遊標是一個存儲在MySQL服務器上的數據庫查詢,它不是一條SELECT語句,而是被該語句檢索出來的結果集。在存儲了遊標以後,應用程序能夠根據須要滾動或瀏覽其中的數據。oop
遊標主要用於交互式應用,其中用戶須要滾動屏幕上的數據,並對數據進行瀏覽或做出更改。學習
注意:只能用於存儲過程 不像多數DBMS,MySQL遊標只能用於存儲過程(和函數)。this
2、使用遊標spa
使用遊標設計幾個明確的步驟。設計
(1)在可以使用遊標前,必須聲明(定義)它。在這個過程實際上沒有檢索數據,它只是定義要使用的SELECT語句。
(2)一旦聲明後,必須打開遊標以供使用。在這個過程用前面定義的SELECT語句把數據實際檢索出來。
(3)對於填有數據的遊標,根據須要取出(檢索)各行。
(4)在結束遊標使用時,必須關閉遊標。
在聲明遊標後,可根據須要頻繁地打開和關閉遊標。在遊標打開後,可根據須要頻繁地執行取操做。
一、建立遊標
遊標用DECLARE語句建立。DECLARE命名遊標,並定義相應的SELECT語句,根據須要帶WHERE和其餘子句。例如,下面的語句定義了名爲ordernumbers的遊標,使用了能夠檢索全部訂單的SELECT語句。
CREATE PROCEDURE processorders() BEGIN DECLARE ordernumber CURSOR FOR SELECT order_num FROM orders; END;
分析:這個存儲過程並無作不少事情,DECLARE語句用來定義和命名遊標,這裏爲ordernumbers。存儲過程處理完成後,遊標就消失(由於它侷限於存儲過程)。
在定義遊標以後,能夠打開它。
二、打開和關閉遊標
遊標用OPEN CURSOR語句來打開:
OPEN ordernumbers;
分析:在處理OPEN語句時執行查詢,存儲檢索出的數據以供瀏覽器和滾動。
遊標處理完成後,應當使用以下語句關閉遊標:
CLOSE ordernumbers;
分析:CLOSE釋放遊標使用的全部內部內存和資源,所以在每一個遊標再也不須要時都應該關閉。
在一個遊標關閉後,若是沒有從新打開,則不能使用它。可是,使用聲明過的遊標不須要再次聲明,用OPEN語句打開它就能夠了。
注意:隱含關閉 若是你不明確關閉遊標,MySQL將會在到達END語句時自動關閉它。
下面是前面例子的修改版本:
CREATE PROCEDURE processorders() BEGIN -- Declare the cursor DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- Open the cursor OPEN ordernumbers; -- Close the cursor CLOSE ordernumbers; END;
分析:這個存儲過程聲明、打開和關閉一個遊標。但對檢索出的數據什麼也沒作。
三、使用遊標數據
在一個遊標被打開後,可使用FETCH語句分別訪問它的每一行。FETCH指定檢索什麼數據(所需的列),檢索出來的數據存儲在什麼地方。它還向前移動遊標中的內部行指針,使下一條FETCH語句檢索下一行(不重複讀取同一行)。
第一個例子從遊標中檢索單個行(第一行):
CREATE PROCEDURE processorders() BEGIN -- Declare local variable DECLARE o INT; -- Declare the cursor DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- Open the cursor OPEN ordernumbers; -- Get order number FETCH ordernumbers INTO o; --Close the cursor CLOSE ordernumbers; END;
分析:其中FETCH用來檢索當前行的order_num列(將自動從第一行開始)到一個名爲o的局部聲明的變量中。對檢索出的數據不作任何處理。
在下一個例子中,循環檢索數據,從第一行到最後一行:
CREATE PROCEDURE processorders() BEGIN -- Declare local variable DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT; -- Declare the cursor DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- Declare continue handler DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; -- Open the cursor OPEN ordernumbers; -- Loop through all rows REPEAT -- Get order number FETCH ordernumbers INTO o; -- End of loop UNTIL done END REPEAT; --Close the cursor CLOSE ordernumbers; END;
分析:與前一個例子同樣,這個例子使用FETCH檢索當前order_num到聲明的名爲o的變量中。但與前一個例子不同的是,這個例子中的FETCH是在REPEAT內,所以它反覆執行直到done爲真(由UTIL done END REPEAT;規定)。爲使它起做用,用一個DEFAULT 0(假,不結束)定義變量done。那麼,done怎樣才能在結束時被設置爲真呢?答案是用如下語句:
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
這條語句定義了一個CONTINUE HANDLER,它是在條件出現時被執行的代碼。這裏,它指出當SQLSTATE '02000'出現時,SET done = 1。SQLSTATE ‘02000’是一個未找到條件,當REPEAT因爲沒有更多的行供循環而不能繼續時,出現這個條件。
注意:DECLARE語句的次序 DECLARE語句的發佈存在特定的次序。用DECLARE語句定義的局部變量必須在定義任意遊標或句柄以前定義,而句柄必須在遊標以後定義。不遵照此順序將產生錯誤消息。
若是調用這個存儲過程,它將定義幾個變量和一個CONTINUE HANDLER,定義並打開一個遊標,重複讀取全部行,而後關閉遊標。
若是一切正常,你能夠在循環內放入任意須要的處理(在FETCH語句以後,循環結束以前)。
注意:循環或重複? 除這裏使用的REPEAT語句外,MySQL還支持循環語句,它可用來重複執行代碼,直到使用LEAVE語句手動退出爲止。一般REPEAT語句的語法使它更適合於對遊標進行循環。
爲了把這些內容組織起來,下面給出咱們的遊標存儲過程樣例的更進一步修改的版本,此次對提取出的數據進行某種實際的處理:
CREATE PROCEDURE processorders() BEGIN -- Declare local variable DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT; DECLARE t DECIMAL(8,2); -- Declare the cursor DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- Declare continue handler DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; -- Declar a table to store the results CREATE TABLE IF NOT EXTSTS ordertotals (order_num INT,total DECIMAL(8,2)); -- Open the cursor OPEN ordernumbers; -- Loop through all rows REPEAT -- Get order number FETCH ordernumbers INTO o; --Get the total for this order CALL ordertotal(o,1,t); --Insert order and total into ordertitals INSERT INTO ordertotals(order_num.total) VALUES(o,t); -- End of loop UNTIL done END REPEAT; --Close the cursor CLOSE ordernumbers; END;
分析:在這個例子中,咱們增長了另外一個名爲t的變量(存儲每一個訂單的合計)。此存儲過程還在運行中建立了一個新表(若是它不存在的話),名爲ordertotals。這個表將保存存儲過程生成的結果。FETCH像之前同樣取每一個order_num,而後用CALL執行另外一個存儲過程(咱們在前一章中建立)來計算每一個訂單的帶稅的合計(結果存儲到t)。最後,用INSERT保存每一個訂單的訂單號和合計。
此存儲過程不返回數據,但它可以建立和填充另外一個表,能夠用一條簡單的SELECT語句查看該表:
SELECT * FROM ordertotals;
這樣,咱們就獲得了存儲過程、遊標、逐行處理以及存儲過程調用其餘存儲過程的一個完整的工做樣例。
3、小結
本博介紹了什麼是遊標以及爲何要使用遊標,舉了演示基本遊標使用的例子,而且講解了對遊標結果進行循環以及逐行處理的技術。