游標:能夠對結果集中的每一條記錄進行定位,并對指向的記錄中的數(shù)據(jù)進行操作的數(shù)據(jù)結構。
目前創(chuàng)新互聯(lián)已為近千家的企業(yè)提供了網(wǎng)站建設、域名、雅安服務器托管、網(wǎng)站托管維護、企業(yè)網(wǎng)站設計、寧鄉(xiāng)網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
創(chuàng)建游標: CREATE FUNCTION 函數(shù)名稱 (參數(shù))RETURNS 數(shù)據(jù)類型 程序體
存儲過程中使用游標的4個步驟:定義游標、打開游標、讀取游標數(shù)據(jù)和關閉游標。
定義游標: DECLARE 游標名 CURSOR FOR 查詢語句
打開游標: OPEN 游標名稱;
讀取游標數(shù)據(jù): FETCH 游標名 INTO 變量列表;
關閉游標: CLOSE 游標名;
條件處理語句: DECLARE 處理方式[CONTINUE 或EXIT] HANDLER FOR 問題 操作;
流程控制語句:跳轉語句(ITERATE語句和LEAVE語句)、循環(huán)語句(LOOP、WHILE、REPEAT)、條件判斷語句(IF語句和CASE語句)
創(chuàng)建游標: CREATE FUNCTION 函數(shù)名稱 (參數(shù))RETURNS 數(shù)據(jù)類型 程序體
存儲函數(shù)與存儲過程很像,但有幾個不同點:
1、存儲函數(shù)必須返回一個值或者數(shù)據(jù)表,存儲過程可以不返回。
2、存儲過程可以通過CALL語句調用,存儲函數(shù)不可以
3、存儲函數(shù)可以放在查詢語句中使用,存儲過程不可以
4、存儲過程的功能更強大,包括能夠執(zhí)行對表的操作(比如創(chuàng)建表、刪除表等)和事務操作
游標操作步驟包含4個:定義游標、打開游標、讀取游標數(shù)據(jù)和關閉游標。
1、創(chuàng)建存儲過程
MySQL 存儲過程中,使用游標查詢,返回的是結果集時,如何查看調用存儲過程輸出結果呢?
解決方案:存儲過程不返回數(shù)據(jù),但它能創(chuàng)建和填充另一個表。所以在存儲過程運行中創(chuàng)建臨時表。該臨時表將保存存儲過程中生成的結果集,在遍歷游標時,用insert保存每條數(shù)據(jù)到臨時表中。后續(xù)調用時可以用select語句查詢臨時表中的存儲過程運行結果。
以下有 三種方式 使用游標創(chuàng)建一個存儲過程,統(tǒng)計某一部門下的員工信息
方法一:Loop循環(huán)
調用存儲過程:
方法二:While 循環(huán)
調用存儲過程:
方法三:REPEAT 循環(huán)
調用存儲過程:
上述三種實現(xiàn)方法在測試過程中遇到下述問題。
調用存儲過程查詢臨時表輸出結果時,會發(fā)現(xiàn)多循環(huán)了一次,像這樣:
解決方法:
在遍歷游標查詢結果時,先判斷游標的結束標志(done) 是否是為1,如果不是1,則向臨時表中插入數(shù)據(jù)。
--傳入id,輸出name和sex的存儲過程,這里同個id有多條數(shù)據(jù),所以需要用到游標。
DELIMITER //
CREATE PROCEDURE p5(IN v_id INT)
BEGIN
DECLARE nodata INT DEFAULT 0;#注意:這個變量聲明必須放在游標聲明前面
DECLARE v_name VARCHAR(30);
DECLARE v_sex CHAR(3);
DECLARE c_ns CURSOR FOR SELECT NAME,sex FROM t WHERE id = v_id;
DECLARE EXIT HANDLER FOR NOT FOUND SET nodata = 1;#當讀到數(shù)據(jù)的最后一條時,設置變量為1
OPEN c_ns;
WHILE nodata = 0 DO#判斷是不是到了最后一條數(shù)據(jù)
FETCH c_ns INTO v_name,v_sex;
SELECT v_name,v_sex,nodata;
END WHILE; ?
CLOSE c_ns;
END
//
--執(zhí)行該存儲過程
mysql call p5(2);
+--------+-------+--------+??
|?v_name?|?v_sex?|?nodata?|??
+--------+-------+--------+??
|?song???|?女????|??????0?|??
+--------+-------+--------+??
1?row?in?set?(0.04?sec)??
+--------+-------+--------+??
|?v_name?|?v_sex?|?nodata?|??
+--------+-------+--------+??
|?dan????|?男????|??????0?|??
+--------+-------+--------+??
1?row?in?set?(0.05?sec)??
Query?OK,?0?rows?affected,?1?warning?(0.05?sec)
--注意:CONTINUE??會繼續(xù)當前的block?中的語句,?它在set?done=1?后繼續(xù)執(zhí)行下一個語句。EXIT??則在?set?done=1?后離開當前的語句塊
所以這里用了EXIT(黃色陰影部分).
如果是continue,結果如下:
mysql?call?p5(2);??
-?//??
+--------+-------+??
|?v_name?|?v_sex?|??
+--------+-------+??
|?song???|?女????|??
+--------+-------+??
1?row?in?set?(0.00?sec)??
+--------+-------+??
|?v_name?|?v_sex?|??
+--------+-------+??
|?dan????|?男????|??
+--------+-------+??
1?row?in?set?(0.01?sec)??
+--------+-------+??
|?v_name?|?v_sex?|??
+--------+-------+??
|?dan????|?男????|??
+--------+-------+??
1?row?in?set?(0.02?sec)??
Query?OK,?0?rows?affected,?1?warning?(0.03?sec)