使用遊標

摘要: 本篇博客僅做爲筆記,若有侵權,請聯繫,當即刪除(網上找博客學習,而後手記筆記,因紙質筆記不便保存,因此保存到網絡筆記)。數據庫

  本博客將講授什麼是遊標以及如何使用遊標。瀏覽器

  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、小結

  本博介紹了什麼是遊標以及爲何要使用遊標,舉了演示基本遊標使用的例子,而且講解了對遊標結果進行循環以及逐行處理的技術。

相關文章
相關標籤/搜索