使用游標(什么是游標、如何使用游標)


  已知MySQL檢索操作返回一組稱為結果集的行。這組返回的行都是與SQL語句相匹配的行(零行或者多行)。使用簡單的SQL語句,例如,沒有辦法得到第一行、下一行或前10行,也不存在每次一行地處理所有行的簡單辦法(相對於成批的處理它們)。

  有時,需要在檢索出來的行中前進或者后退一行或者多行,這就是使用游標的原因,游標(cursor)是一個存儲在MySQL服務器上的數據庫查詢。它不是一條SQL語句,而是被SQL語句檢索出來的結果集。在存儲了游標只有,用戶可以根據需要滾動或瀏覽其中的數據。

  游標主要用於交互式應用,其中用戶需要滾動屏幕中的數據,並對數據進行瀏覽或者作出更改。

  不像多數DBMS,MySQL游標只能用於存儲過程(和函數)。

  使用游標:

  使用游標明確的幾個步驟:

  1.在能夠使用游標前,必須聲明(定義)它。這個過程實際上沒有檢索數據,它只是要定義要使用的SELECT語句。

  2.一旦聲明后,鼻血打開游標以供使用。這個過程用前面定義的SELECT語句把數據實際檢索出來。

  3.對於填有數據的游標,根據需要取出(檢索)各行。

  4.在結束游標使用時,必須關閉游標。

  在聲明游標后,可以根據需要頻繁地打開或者關閉游標。在游標打開后,可根據需要頻繁地執行取操作。

  創建游標:

  游標用DECLARE語句創建。DECLARE命名游標,並定義相應的SELECT語句,根據需要帶WHERE和其它子句。例如,下面的語句定義了名為ordernumbers的游標,使用了可以檢索的所有訂單的SELECT語句。

CREATE PROCEDURE processorders()
BEGIN
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FORM orders;
END;

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

  在定義游標之后,可以打開它。

  打開和關閉游標:

  打開游標:OPEN ordernumbers;在處理OPEN語句時執行查詢,存儲檢索出的數據以供瀏覽和滾動。

  關閉游標:CLOSE ordernumbers;CLOSE釋放游標使用的所有內部內存和資源,因此在每個游標不再需要時都應該關閉。

  隱含關閉:如果不明確關閉游標,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 variables;
    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;--用來檢索當前行的order_num列(將自動從第一行開始)到一個名為o的局部聲明的變量中。對檢索出的數據不做任何處理。

    --Close the cursor
    CLOSE ordernumbers;
END; 

  例子:循環檢索數據,從第一行到最后一行。

CREATE PROCEDURE processorders()
BEGIN
    --Declare local variables;
    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;

    --Get order number
    FETCH ordernumbers INTO o;--用來檢索當前行的order_num列(將自動從第一行開始)到一個名為o的局部聲明的變量中。對檢索出的數據不做任何處理。

    --Close the cursor
    CLOSE ordernumbers;
END; 

  與前一個例子一樣,這個例子使用FETCH檢索當前order_num到聲明的名為o的變量中。但是與前一個例子不一樣的是,這個例子中的FETCH是在REPEAT內,因此它反復執行到done為真(由UNTIL 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由於沒有更多的行功勛換而不能繼續時,出現這個條件。

  MySQL錯誤代碼列表:請參閱http://dev.mysql.com/doc/mysql/en/error-handling.html

  DECLARE語句的次序,DECALRE語句的發布存在特定的次序。用DECLARE語句定義的局部變量必須在定義任意游標或句柄之前定義,而句柄必須在游標之后定義。不遵守詞順序將產生錯誤消息。

  如果調用這個存儲過程,它將定義幾個變量和一個CONTINUE HANDLER,定義並打開一個游標,重復讀取所有行,然后關閉游標。

  重復或循環:

  除這里使用的REPEAT外,MySQL還支持循環語句,它可以用來重復執行代碼,直到使用LEAVE語句手動退出為止。通常REPEAT語句得語法使它更適合於對游標進行循環。

  為了把這些內容組織起來,下面對游標存儲過樣例更進一步的修改,這次對取出的數據進行某種實際的處理。

  

CREATE PROCEDURE processorders()
BEGIN
    --Declare local variables;
    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;

    --Create table to store the results
    CREATE TABLE IF NOT EXISTS 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 ordertotals
            INSERT INTO ordertotals(order_num,totals)
            VALUES(o,t);

   -End of loop
   UNTIL done END REPEAT;

    --Get order number
    FETCH ordernumbers INTO o;--用來檢索當前行的order_num列(將自動從第一行開始)到一個名為o的局部聲明的變量中。對檢索出的數據不做任何處理。

    --Close the cursor
    CLOSE ordernumbers;--關閉游標
END; 

  此存儲過程不返回數據,但它可以創建並填充另一個表,可以用一條簡單的SELECT語句查看該表;

SELECT * 
FROM ordertotals;

  這樣,我們就得到了存儲過程、游標、逐行處理以及存儲過程調用其他存儲過程的一個完整的工作示例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM