在本教學中,您將學習如何在存儲過程中使用MySQL游標來遍曆SELECT
語句返回的結果集。
MySQL游標簡介
要處理存儲過程中的結果集,請使用游標。游標允許您迭代查詢返回的一組行,並相應地處理每行。
MySQL游標為只讀,不可滾動和敏感。
- 只讀:無法通過游標更新基礎表中的數據。
- 不可滾動:只能按照SELECT語句確定的順序獲取行。不能以相反的順序獲取行。 此外,不能跳過行或跳轉到結果集中的特定行。
- 敏感:有兩種游標:敏感游標和不敏感游標。敏感游標指向實際數據,不敏感游標使用數據的臨時副本。敏感游標比一個不敏感的游標執行得更快,因為它不需要臨時拷貝數據。但是,對其他連接的數據所做的任何更改都將影響由敏感游標使用的數據,因此,如果不更新敏感游標所使用的數據,則更安全。 MySQL游標是敏感的。
使用MySQL游標
首先,必須使用DECLARE
語句聲明游標:
DECLARE cursor_name CURSOR FOR SELECT_statement;
游標聲明必須在變數聲明之後。如果在變數聲明之前聲明游標,MySQL將會發出一個錯誤。游標必須始終與SELECT
語句相關聯。
接下來,使用OPEN
語句打開游標。OPEN
語句初始化游標的結果集,因此您必須在從結果集中提取行之前調用OPEN
語句。
OPEN cursor_name;
然後,使用FETCH
語句來檢索游標指向的下一行,並將游標移動到結果集中的下一行。
FETCH cursor_name INTO variables list;
之後,可以檢查是否有任何行記錄可用,然後再提取它。
最後,調用CLOSE
語句來停用游標並釋放與之關聯的記憶體,如下所示:
CLOSE cursor_name;
當游標不再使用時,應該關閉它。
當使用MySQL游標時,還必須聲明一個NOT FOUND
處理程式來處理當游標找不到任何行時的情況。 因為每次調用FETCH
語句時,游標會嘗試讀取結果集中的下一行。 當游標到達結果集的末尾時,它將無法獲得數據,並且會產生一個條件。 處理程式用於處理這種情況。
要聲明一個NOT FOUND
處理程式,參考以下語法:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
finished
是一個變數,指示游標到達結果集的結尾。請注意,處理程式聲明必須出現在存儲過程中的變數和游標聲明之後。
下圖說明瞭MySQL游標如何工作。
MySQL游標示例
為了更好地演示,我們將開發一個存儲過程,來獲取MySQL示例資料庫(zaixiandb)中employees
表中所有員工的電子郵件列表。
首先,聲明一些變數,一個用於迴圈員工電子郵件的游標和一個NOT FOUND
處理程式:
DECLARE finished INTEGER DEFAULT 0;
DECLARE email varchar(255) DEFAULT "";
-- declare cursor for employee email
DEClARE email_cursor CURSOR FOR
SELECT email FROM employees;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
接下來,使用OPEN
語句打開email_cursor
:
OPEN email_cursor;
然後,迭代電子郵件列表,並使用分隔符號(;
)連接每個電子郵件:
get_email: LOOP
FETCH email_cursor INTO v_email;
IF v_finished = 1 THEN
LEAVE get_email;
END IF;
-- build email list
SET email_list = CONCAT(v_email,";",email_list);
END LOOP get_email;
之後,在迴圈中,使用v_finished
變數來檢查列表中是否有任何電子郵件來終止迴圈。
最後,使用CLOSE
語句關閉游標:
CLOSE email_cursor;
build_email_list
存儲過程所有代碼如下:
DELIMITER $$
CREATE PROCEDURE build_email_list (INOUT email_list varchar(4000))
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_email varchar(100) DEFAULT "";
-- declare cursor for employee email
DEClARE email_cursor CURSOR FOR
SELECT email FROM employees;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN email_cursor;
get_email: LOOP
FETCH email_cursor INTO v_email;
IF v_finished = 1 THEN
LEAVE get_email;
END IF;
-- build email list
SET email_list = CONCAT(v_email,";",email_list);
END LOOP get_email;
CLOSE email_cursor;
END$$
DELIMITER ;
可以使用以下腳本測試build_email_list
存儲過程:
SET @email_list = "";
CALL build_email_list(@email_list);
SELECT @email_list;
注:由於內容比較長,這裏就不放上輸出結果了。
在本教學中,我們向您展示了如何使用MySQL游標來迭代結果集並相應地處理每一行。