MySQL遊標簡析
阿新 • • 發佈:2019-01-01
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 |