MySQL 游標(biāo)的基本用法

MySQL游標(biāo)只能用于存儲(chǔ)過程。
使用游標(biāo)的步驟:
①在能夠使用游標(biāo)前,必須聲明它。這個(gè)過程實(shí)際上沒有檢索數(shù)據(jù),它只是定義要使用的select語句。
游標(biāo)的定義格式:
DECLARE 光標(biāo)名稱 CURSOR FOR 查詢語法
declare cursor_name cursor for select_statement

②聲明游標(biāo)后,要打開游標(biāo)以供使用。這個(gè)過程就是把前面定義的select語句把數(shù)據(jù)實(shí)際檢索出來。
打開游標(biāo)格式:
OPEN 光標(biāo)名稱
open cursor_name

③對(duì)于填有數(shù)據(jù)的游標(biāo),根據(jù)需要取出(檢索)各行。
在游標(biāo)被打開后,使用fetch語句分別訪問它的每一行。fetch指定檢索的列,并存儲(chǔ)到已定義好的列中。然后繼續(xù)向前移動(dòng)游標(biāo)中的內(nèi)部行指針,使下一條fetch語句檢索下一行(不重復(fù)讀取同一行)。
取游標(biāo)中的數(shù)據(jù)格式:
FETCH 光標(biāo)名稱 INFO var_name [,var_name ].....
fetch cursor_name info var_name

④在結(jié)束游標(biāo)使用后,必須關(guān)閉游標(biāo)。
關(guān)閉游標(biāo)
CLOSE curso_name;
close 光標(biāo)名稱

創(chuàng)建部門表:

CREATE TABLE IF NOT EXISTS depart(
    bumenTableid INT(11) NOT NULL primary key auto_increment COMMENT'部門編號(hào)(主鍵)',
    bumenTablename VARCHAR(50) COMMENT'部門名稱',
    bumenTableaddress VARCHAR(50) COMMENT'部門地址'
);

添加部門表數(shù)據(jù):

INSERT INTO  depart(bumenTablename,bumenTableaddress) VALUES 
('銷售部','銷售部地址'),
('學(xué)業(yè)部','學(xué)業(yè)部地址'),
('董事部','董事部地址'),
('人力資源部','人力資源部地址'),
('產(chǎn)品部','產(chǎn)品部地址');

創(chuàng)建員工表:

CREATE TABLE emp(
    id INT(11) NOT NULL primary key auto_increment COMMENT'員工編號(hào)',
    yuangongname VARCHAR(50) COMMENT'員工姓名',
    word VARCHAR(50) COMMENT'員工工作',
    lineManagerId INT(11) COMMENT'員工直屬領(lǐng)導(dǎo)編號(hào)',
    entryTime datetime COMMENT'員工入職時(shí)間',
    wage INT(11) COMMENT'員工工資',
    bonus INT(11) COMMENT'員工獎(jiǎng)金',
    bumenTableId INT(11) NOT NULL COMMENT'對(duì)應(yīng)部門表的外鍵',
    FOREIGN KEY(bumenTableId) REFERENCES  depart(bumenTableid)
);

添加員工表數(shù)據(jù):

INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小王', '職員', '2', '2017-06-14 14:30:50', '4000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小李', '銷售經(jīng)理', '4', '2016-08-16 14:32:08', '20800', '5000', '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小張', '產(chǎn)品經(jīng)理', '4', '2016-05-04 14:33:05', '22700', null, '5');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小高', '職員', null, '2015-07-08 14:33:54', '5000', null, '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('小劉', 'HR經(jīng)理', '4', '2017-11-08 14:35:35', '10000', null, '4');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('王一', '學(xué)業(yè)經(jīng)理', '4', '2016-11-01 14:36:28', '20000', '5000', '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('王二', '職員', '3', '2018-03-22 14:38:44', '5000', null, '5');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李四', '職員', '5', '2017-04-01 14:39:53', '5000', null, '4');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李一', '職員', '6', '2018-08-01 14:40:43', '5000', null, '2');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李二', '職員', '2', '2018-05-17 14:41:30', '5000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('李三', '職員', '2', '2017-05-01 14:42:20', '5000', null, '1');
INSERT INTO emp (yuangongname,word,lineManagerId,entryTime,wage,bonus,bumenTableId) VALUES ('公司人員', '其他', null, '2015-07-08 15:31:52', '1234567', '1234567', '5');

示例1(游標(biāo)返回單條記錄):查詢某個(gè)員工的姓名,職位、工資等

DROP PROCEDURE IF EXISTS pro_empIndepart;

delimiter //
CREATE PROCEDURE pro_empIndepart (IN empid INT)
    READS SQL DATA
BEGIN
    DECLARE  c_id INT;
    DECLARE  c_empname VARCHAR(50);
    DECLARE  c_job VARCHAR(50);
    DECLARE  c_salary INT;
    DECLARE cur CURSOR for select  e.id,e.yuangongname,e.word,e.wage from emp e where  e.id =  empid;    
    OPEN cur;
        FETCH cur INTO c_id,c_empname,c_job,c_salary;
        SELECT c_id,c_empname,c_job,c_salary;
    CLOSE cur;
END//

delimiter ;

調(diào)用存儲(chǔ)過程:

CALL pro_empIndepart(5);
image.png

上述示例返回的是單條記錄,所以不需要遍歷結(jié)果集。

示例2(游標(biāo)返回結(jié)果集):查詢某個(gè)部門下員工信息

DROP PROCEDURE IF EXISTS empIndepart_list;

delimiter //
create procedure empIndepart_list(IN departid INT)
begin
    declare done boolean default 0;
    DECLARE  c_id,c_salary INT;
  -- 注意 接收游標(biāo)值為中文時(shí) 需要 給變量 指定 字符集為utf8
  DECLARE  c_empname,c_job VARCHAR(50) character set utf8;

    declare cur cursor
            for
          select  e.id,e.yuangongname,e.word,e.wage from emp e where e.bumenTableId=departid;
  declare continue handler for sqlstate '02000' set done=1;
    create table if not  exists emp_dempart_temp(id int,empname VARCHAR(50),job VARCHAR(50),salary int);
  truncate TABLE emp_dempart_temp;

    open cur;
         REPEAT
            fetch cur into  c_id,c_empname,c_job,c_salary;
                if done != 1 then
                    insert into emp_dempart_temp(id,empname,job,salary) values(c_id,c_empname,c_job,c_salary);
        end if;
    until done =1 end repeat;
    close cur;
  
end//
delimiter;

該示例,使用fetch檢索指定列到聲明的4個(gè)變量中。但與上一個(gè)例子不同的是,這個(gè)fetch是在repeat內(nèi),因?yàn)樗磸?fù)執(zhí)行直到done為真(由 until done =1 end repeat;規(guī)定)。為了使該語句起作用,用一個(gè)default 0來定義變量done。那么done怎樣才能在結(jié)束時(shí)被設(shè)置為真呢?要使用以下語句:

declare continue handler for SQLSTATE '02000' SET done=1;

該語句定義了一個(gè)continue handler,它是在條件出現(xiàn)時(shí)被執(zhí)行的代碼。當(dāng)SQLSTATE‘02000’出現(xiàn)時(shí),set done=1。SQLSTATE’02000’是一個(gè)未找到條件,當(dāng)REPEAT由于沒有更多的行供循環(huán)而不能繼續(xù)時(shí),出現(xiàn)該條件。

注意:用declare定義的局部變量必須在定義任意游標(biāo)或句柄之前定義,而句柄必須在游標(biāo)之后定義(例如上面done語句)。不遵守此順序?qū)a(chǎn)生錯(cuò)誤消息。

執(zhí)行該存儲(chǔ)過程,它將定義幾個(gè)變量和一個(gè)continue handler,定義并打開一個(gè)游標(biāo),重復(fù)讀取所有行,在fetch語句之后,循環(huán)結(jié)束之前可以在循環(huán)內(nèi)放入任意需要的處理,例如向臨時(shí)表中插入數(shù)據(jù),查詢某變量的值等。
上述示例,在打開游標(biāo)之前創(chuàng)建了一個(gè)臨時(shí)表:emp_dempart_temp,在遍歷游標(biāo)查詢結(jié)果時(shí),在滿足done != 1的條件下向該表插入 存儲(chǔ)過程中游標(biāo)查詢生成的結(jié)果。

調(diào)用存儲(chǔ)過程:

CALL empIndepart_list(2);

使用select語句查看emp_dempart_temp的內(nèi)容:

select * from emp_dempart_temp;
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容