先聲明一個游標,語法:

成都創(chuàng)新互聯(lián)是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計,網(wǎng)站模板,微信公眾號開發(fā),軟件開發(fā),成都小程序開發(fā),10年建站對茶樓設(shè)計等多個領(lǐng)域,擁有豐富的網(wǎng)站設(shè)計經(jīng)驗。
DECLARE v_1 VARCHAR(16);
DECLARE v_2 VARCHAR(16);
DECLARE c_XXX CURSOR FOR
SELECT c_1, c_2
FROM t_1;
同時聲明一個布爾型的變量FOUND,當循環(huán)的條件不成立時,結(jié)束循環(huán)用的。
DECLARE FOUND BOOLEAN DEFAULT TRUE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET FOUND = FALSE;
在使用游標的時候,要先打開游標,語法:OPEN c_XXX;
使用的時候,要先打開游標,取出第一條數(shù)據(jù),語法: FETCH c_XXX INTO v_1, v_2;
然后才開始執(zhí)行循環(huán),語法:WHILE FOUND DO
執(zhí)行需要執(zhí)行的語句;
取下一條數(shù)據(jù)放到當前游標中,F(xiàn)ETCH c_XXX INTO v_1, v_2;
結(jié)束循環(huán),語法:END WHILE;
結(jié)束游標,語法:CLOSE c_cargo。有什么問題我們再溝通啊。不知道你具體要問題的是什么。
CREATE? PROCEDURE `gk_test`()
COMMENT '測試數(shù)據(jù)'? -- 函數(shù)注釋
BEGIN
DECLARE done INT DEFAULT FALSE;?-- 定義遍歷數(shù)據(jù)結(jié)束標志。非游標變量,需要定義在游標變量前
DECLARE m_id CHAR(32);?-- 定義接收游標數(shù)據(jù)中id變量
DECLARE m_or VARCHAR(255);?--?定義接收游標數(shù)據(jù)中orderno變量
DECLARE m_c INT(11);??--?定義接收游標數(shù)據(jù)中count變量
DECLARE m_soult CURSOR FOR SELECT `id`, `orderno`, count(*) t FROM hb_shipper_order GROUP BY orderno HAVING t 1;???-- 定義游標變量,即接收查詢結(jié)果集
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;??-- 將結(jié)束標志綁定到游標
OPEN m_soult;? ??-- 打開游標
read_loop:LOOP? ?-- 開始循環(huán)。這個是mysql 3種循環(huán)中的1種。
FETCH m_soult INTO m_id,m_or,m_c;???-- 提取游標數(shù)據(jù)
IF done THEN? ?-- 判斷,當為true時
LEAVE read_loop;? ?-- 跳出循環(huán)
END IF;
-- 處理事 自己想處理的事
UPDATE `hb_shipper_waybill` SET
ordernos = REPLACE (`ordernos`, m_or, CONCAT(m_or,'-2')),
goodsname = REPLACE (`goodsname`, m_or, CONCAT(m_or,'-2'))
WHERE `id` IN ( SELECT `waybillid` FROM `hb_shipper_order_waybill_relation` WHERE orderid = m_id);
UPDATE `hb_shipper_order` SET orderno = CONCAT(m_or,'-2') WHERE id = m_id;
END LOOP;? -- 結(jié)束循環(huán)
-- 關(guān)閉游標
CLOSE m_soult;
END
上圖:
DEMO: 2? ? // 通過 存儲過程,處理? copy 數(shù)據(jù)并處理對應(yīng)數(shù)據(jù)關(guān)系
delimiter $$
DROP PROCEDURE IF EXISTS gk;
CREATE DEFINER =? PROCEDURE `gk`(IN pname varchar(255))
COMMENT '測試'
BEGIN
DECLARE new_id CHAR(32);
DECLARE m_id CHAR(32);
DECLARE new_noids VARCHAR(255);
DECLARE done INT DEFAULT 0;
DECLARE m_result CURSOR FOR select id from `xxx`;
DECLARE m_result2 CURSOR FOR select id from `xxx`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TABLE IF EXISTS `xxx`;
CREATE TABLE `xxx` (
`id` char(32) NOT NULL COMMENT 'ID',
`subsystem` char(32) NOT NULL COMMENT '',
`name` varchar(20) NOT NULL COMMENT '',
`type` varchar(15) NOT NULL COMMENT '',
`url` varchar(200) DEFAULT NULL COMMENT '',
`icon` varchar(20) DEFAULT NULL COMMENT '',
`target` varchar(10) NOT NULL DEFAULT '_self' COMMENT '',
`method` mediumtext COMMENT '',
`orderby` smallint(3) NOT NULL DEFAULT '0' COMMENT '',
`parentid` char(32) NOT NULL DEFAULT '0' COMMENT '',
`relateid` char(32) NOT NULL COMMENT '',
`isopen` tinyint(1) NOT NULL DEFAULT '1' COMMENT '',
`nodeids` varchar(255) DEFAULT NULL COMMENT '',
`nodenum` smallint(3) NOT NULL DEFAULT '0' COMMENT '',
`createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '',
`createuser` char(32) NOT NULL DEFAULT '0' COMMENT '',
`updatetime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '',
`udateuser` char(32) NOT NULL DEFAULT '0' COMMENT '',
`deleted` tinyint(1) DEFAULT '0' COMMENT '',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '',
`isdefault` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '',
? ? ? ? ? ? `isdisable` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '',
`projecttype` varchar(255) NOT NULL COMMENT '',
? ? ????PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
INSERT INTO `xxxx` SELECT * FROM `aaa` WHERE `projecttype` = 'T';
UPDATE `xxx` SET `projecttype` = pname;
OPEN m_result;
REPEAT
FETCH m_result INTO m_id;
SET new_id = UPPER(REPLACE(UUID(),'-',''));
UPDATE `xxx` SET `id` = new_id WHERE `id` = m_id;
UPDATE `xxx` SET `parentid` = new_id WHERE `parentid` = m_id;
UNTIL done END REPEAT;
CLOSE m_result;
SET done = 0;
OPEN m_result2;
REPEAT
FETCH m_result2 INTO m_id;
SELECT CONCAT(',', GROUP_CONCAT(`id`)) INTO new_noids FROM `xxx` WHERE `parentid` = m_id;
UPDATE `xxx` SET `nodeids` = new_noids WHERE `id` = m_id;
UNTIL done END REPEAT;????
CLOSE m_result2;
INSERT INTO `aaa` SELECT * FROM `xxx`;
DROP TABLE IF EXISTS xxx;
END $$
delimiter ;
MySQL 存儲過程中,使用游標查詢,返回的是結(jié)果集時,如何查看調(diào)用存儲過程輸出結(jié)果呢?
解決方案:存儲過程不返回數(shù)據(jù),但它能創(chuàng)建和填充另一個表。所以在存儲過程運行中創(chuàng)建臨時表。該臨時表將保存存儲過程中生成的結(jié)果集,在遍歷游標時,用insert保存每條數(shù)據(jù)到臨時表中。后續(xù)調(diào)用時可以用select語句查詢臨時表中的存儲過程運行結(jié)果。
以下有 三種方式 使用游標創(chuàng)建一個存儲過程,統(tǒng)計某一部門下的員工信息
方法一:Loop循環(huán)
調(diào)用存儲過程:
方法二:While 循環(huán)
調(diào)用存儲過程:
方法三:REPEAT 循環(huán)
調(diào)用存儲過程:
上述三種實現(xiàn)方法在測試過程中遇到下述問題。
調(diào)用存儲過程查詢臨時表輸出結(jié)果時,會發(fā)現(xiàn)多循環(huán)了一次,像這樣:
解決方法:
在遍歷游標查詢結(jié)果時,先判斷游標的結(jié)束標志(done) 是否是為1,如果不是1,則向臨時表中插入數(shù)據(jù)。
在數(shù)據(jù)庫中,游標是一個十分重要的概念。游標提供了一種對從表中檢索出的數(shù)據(jù)進行操作的靈活手段,就本質(zhì)而言,游標實際上是一種能從包括多條數(shù)據(jù)記錄的結(jié)果集中每次提取一條記錄的機制。游標總是與一條SQL??選擇語句相關(guān)聯(lián)因為游標由結(jié)果集(可以是零條、一條或由相關(guān)的選擇語句檢索出的多條記錄)和結(jié)果集中指向特定記錄的游標位置組成。當決定對結(jié)果集進行處理時,必須聲明一個指向該結(jié)果集的游標。如果曾經(jīng)用?C?語言寫過對文件進行處理的程序,那么游標就像您打開文件所得到的文件句柄一樣,只要文件打開成功,該文件句柄就可代表該文件。對于游標而言,其道理是相同的。可見游標能夠?qū)崿F(xiàn)按與傳統(tǒng)程序讀取平面文件類似的方式處理來自基礎(chǔ)表的結(jié)果集,從而把表中數(shù)據(jù)以平面文件的形式呈現(xiàn)給程序。
我們知道關(guān)系數(shù)據(jù)庫管理系統(tǒng)實質(zhì)是面向集合的,在MS?SQL?SERVER?中并沒有一種描述表中單一記錄的表達形式,除非使用where??子句來限制只有一條記錄被選中。因此我們必須借助于游標來進行面向單條記錄的數(shù)據(jù)處理。由此可見,游標允許應(yīng)用程序?qū)Σ樵冋Z句select??返回的行結(jié)果集中每一行進行相同或不同的操作,而不是一次對整個結(jié)果集進行同一種操作;它還提供對基于游標位置而對表中數(shù)據(jù)進行刪除或更新的能力;而且,正是游標把作為面向集合的數(shù)據(jù)庫管理系統(tǒng)和面向行的程序設(shè)計兩者聯(lián)系起來,使兩個數(shù)據(jù)處理方式能夠進行溝通。
在數(shù)據(jù)庫開發(fā)過程中,當你檢索的數(shù)據(jù)只是一條記錄時,你所編寫的事務(wù)語句代碼往往使用SELECT?INSERT?語句。但是我們常常會遇到這樣情況,即從某一結(jié)果集中逐一地讀取一條記錄。那么如何解決這種問題呢?游標為我們提供了一種極為優(yōu)秀的解決方案——那就是使用游標。
從字面可以這么理解什么是游標,游標就像是水面上漂浮的一個標記,這個標記可以來回游動,一會游到這里一會游到那里,這里的河水可以理解為是數(shù)據(jù)的集合,這個標記就是在這些數(shù)據(jù)間來回游動。
為什么 MySQL 會有游標這個概念,由于 SQL 語言是面向集合的語句,它每次查詢出來都是一堆數(shù)據(jù)的集合,沒有辦法對其中一條記錄進行單獨的處理。如果要對每條記錄進行單獨處理就需要游標。
游標其實就像是編程語言中的 for/foreach 循環(huán),把一個數(shù)組(數(shù)據(jù)的集合)中每條數(shù)據(jù)一條一條地循環(huán)出來,然后你在 for/foreach 循環(huán)中使用判斷語句對你感興趣的數(shù)據(jù)進行處理。
哪里可以使用游標呢,函數(shù),存儲過程,觸發(fā)器中都可以使用。
說完概念,就來看下游標的固定寫法。不管概念是否理解,記住下面的固定模式也可以完成搬磚任務(wù)。
1、聲明游標
SELECT 語句就是正常的查詢語句,例如:SELECT id,age FROM table;
2、打開游標
在打開游標之前,游標定義的 SQL 語句是不執(zhí)行的。
3、取出記錄
將當前的記錄數(shù)據(jù)存入變量。
當 FETCH 沒有找到記錄時會拋出異常,異常的定義需要下面的 HANDLER FOR 語句。
聲明游標語句中的 SELECT 如果有多個字段,INTO 后面需要多個變量進行接收。
4、設(shè)置結(jié)束條件
這個語句的作用是指定一個條件,告訴程序所有數(shù)據(jù)已經(jīng)循環(huán)完畢,可以結(jié)束了。由于游標是使用 WHILE 循環(huán)進行每條數(shù)據(jù)的讀取,就需要給 WHILE 一個結(jié)束條件。
處理種類:可以是, EXIT 立即結(jié)束。CONTINUE 繼續(xù)下面的處理。
異常的類型:一般指定為 NOT FOUND ,意思是沒有找到任何數(shù)據(jù)。
異常發(fā)生時的處理:當異常發(fā)生時需要做的事情,這里一般改變一個變量的值來記錄異常已經(jīng)發(fā)生了,如如 SET flat = 1 詳細用法查看下面的例子。
5、關(guān)閉游標
實戰(zhàn)代碼:
完畢,看懂沒,如果沒看懂沒關(guān)系,游標處理是一套固定的格式,按照上面例子中固定的格式套入到你的程序就可以了。
比較基礎(chǔ)的
可以用在存儲過程的SQL語句主要有以下類型:
1、
無返回結(jié)果語句,如:INSERT,UPDATE,DROP,
DELETE等
2、
select語句返回單行變量并可傳給本地變量(select
..into)
3、
返回多行結(jié)果集的select語句,并可使用游標循環(huán)處理
注意,存儲過程返回的多行結(jié)果集,可以被客戶端程序(如php)所接收,但要在一個存儲過程中接收另一個存儲過程的結(jié)果集是不可能的,一般解決辦法是存入臨時表供其它過程共用
4、
prepare語句
以下主要講述游標及prepare部分
游標
定義
DECLARE
cursor_name
CURSOR
FOR
SELECT_statement;
游標操作
OPEN
打開游標
OPEN
cursor_name;
FETCH
獲取游標當前指針的記錄,并傳給指定變量列表,注意變量數(shù)必須與游標返回的字段數(shù)一致,要獲得多行數(shù)據(jù),使用循環(huán)語句去執(zhí)行FETCH
FETCH
cursor_name
INTO
variable
list;
CLOSE關(guān)閉游標
CLOSE
cursor_name
;
注意:mysql的游標是向前只讀的,也就是說,你只能順序地從開始往后讀取結(jié)果集,不能從后往前,也不能直接跳到中間的記錄.
一個完整的例子:
--
定義本地變量
DECLARE
o
varchar(128);
--
定義游標
DECLARE
ordernumbers
CURSOR
FOR
SELECT
callee_name
FROM
account_tbl
where
acct_timeduration=10800;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
no_more_departments=1;
SET
no_more_departments=0;
--
打開游標
OPEN
ordernumbers;
--
循環(huán)所有的行
REPEAT
--
Get
order
number
FETCH
ordernumbers
INTO
o;
update
account
set
allMoney=allMoney+72,lastMonthConsume=lastMonthConsume-72
where
NumTg=@o;
--
循環(huán)結(jié)束
UNTIL
no_more_departments
END
REPEAT;
--
關(guān)閉游標
CLOSE
ordernumbers;
標題名稱:mysql游標怎么用,mysql游標使用
文章來源:http://chinadenli.net/article38/dsgcjpp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、、網(wǎng)站營銷、網(wǎng)站建設(shè)、建站公司、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)