MySQL 游標
- SQL陳述句是“面向集合編程”,重點在于“獲得什么”,而不是“如何獲得”,
- 有時候我們不需要對查詢結構集的每一條都進行相同的操作,而是只操作其中的某些行,這時候就需要面向程序的編程方法,而游標就是面向程序編程方式的體現
- 游標就相當于“指標”,它一次只指向一行
- 游標的作用就是用于對查詢資料庫所回傳的記錄進行遍歷,以便進行相應的操作
游標的使用
宣告(給定結果集)、打開、通過游標獲取資料、關閉、釋放游標
-
宣告,給定結果集,存盤程序結束后游標就被清理
DECLARE cursor_name CURSOR FOR (SELECT...); -
打開游標,將結果集送到游標作業區
OPEN cursor_name; -
通過游標獲取資料
游標先判斷當前行是否為空,若為空則改變done,若不為空則將資料存放到臨時變數中,讀取后進入下一行為下次讀取做準備,
一定要想明白FETCH的運行方式,不然可能會出現重復FETCH到資料的情況
FETCH cursor_name INTO (變數名s); -
關閉游標
CLOSE cursor_name; -
因為每次呼叫FETCH游標就會嘗試下一行,因此還要宣告一個
NOT FOUND處理程式來處理游標讀取不到下一行的情況DECLARE CONTINUE HANDLER FOR not found SET done = true;或者
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done = true;SQLSTATE '02000'可以看做和not found一樣,SQLSTATE '02000'是當沒有更多的行以供回圈時出現的一個條件,上面兩種都可行,至于done賦值為true還是為1,就要看done是如何定義的,當然定義為INIT的為可以初始化為true
使用舉例1
現有如下資料表
mysql> select * from t;
+----+------+-----------------+
| id | nums | content |
+----+------+-----------------+
| 1 | 2 | NULL |
| 2 | 6 | 二六一十二 |
| 3 | 3 | 三三得九 |
+----+------+-----------------+
3 rows in set (0.00 sec)
我們通過游標讀取每一行并實作將nums匯入到新資料表中,在實際作業中這種方式可以大大減少我們"分表"時的操作難度,
DELIMITER //
CREATE PROCEDURE transferData()
BEGIN
DECLARE temp_num INT;
DECLARE done BOOLEAN DEFAULT false;
DECLARE cur CURSOR FOR select nums FROM t;
DECLARE continue HANDLER FOR not found SET done = true;
CREATE TABLE IF NOT EXISTS t2 (auto_id int PRIMARY KEY AUTO_INCREMENT, val int not null);
OPEN cur;
REPEAT
IF NOT done THEN
FETCH cur INTO temp_num;
INSERT INTO t2 (val) VALUES (temp_num);
END IF;
UNTIL done=true END REPEAT;
CLOSE cur;
SELECT * from t2;
END//
DELIMITER ;
執行該存盤程序后自動顯示如下結果:
mysql> select * from t2;
-> //
+---------+-----+
| auto_id | val |
+---------+-----+
| 1 | 2 |
| 2 | 6 |
| 3 | 3 |
| 4 | 3 |
+---------+-----+
4 rows in set (0.00 sec)
我們會發現,為什么這里多了一行資料?看起來是被重復FETCH并插入了,究其原因,是因為沒有理清楚FETCH的運作方式---沒有搞清楚什么時候FETCH會改變done
如果我們改成
CREATE PROCEDURE transferData2()
BEGIN
DECLARE temp_num INT;
DECLARE done BOOLEAN DEFAULT false;
DECLARE cur CURSOR FOR select nums FROM t;
DECLARE continue HANDLER FOR not found SET done = true;
CREATE TABLE IF NOT EXISTS t3 (auto_id int PRIMARY KEY AUTO_INCREMENT, val int not null);
OPEN cur;
REPEAT
FETCH cur INTO temp_num;
IF NOT done THEN
INSERT INTO t3 (val) VALUES (temp_num);
END IF;
UNTIL done=true END REPEAT;
CLOSE cur;
SELECT * from t3;
END//
則結果會符合我們的預期
mysql> select * from t3//
+---------+-----+
| auto_id | val |
+---------+-----+
| 1 | 2 |
| 2 | 6 |
| 3 | 3 |
+---------+-----+
3 rows in set (0.00 sec)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/19753.html
標籤:MySQL
上一篇:MySQL補充——忘記密碼怎么辦
下一篇:redis中hash資料型別
