Mysql系列的目標是:經過這個系列從入門到全面掌握一個高級開發所須要的所有技能。html
這是Mysql系列第19篇。java
環境:mysql5.7.25,cmd命令中進行演示。mysql
代碼中被[]包含的表示可選,|符號分開的表示可選其一。sql
需求背景
當咱們須要對一個select的查詢結果進行遍歷處理的時候,如何實現呢?微信
此時咱們須要使用遊標,經過遊標的方式來遍歷select查詢的結果集,而後對每行數據進行處理。函數
本篇內容
- 遊標定義
- 遊標做用
- 遊標使用步驟
- 遊標執行過程詳解
- 單遊標示例
- 嵌套遊標示例
準備數據
建立庫:javacode2018
oop
建立表:test一、test二、test3fetch
/*建庫javacode2018*/
drop database if exists javacode2018;
create database javacode2018;
/*切換到javacode2018庫*/
use javacode2018;
DROP TABLE IF EXISTS test1;
CREATE TABLE test1(a int,b int);
INSERT INTO test1 VALUES (1,2),(3,4),(5,6);
DROP TABLE IF EXISTS test2;
CREATE TABLE test2(a int);
INSERT INTO test2 VALUES (100),(200),(300);
DROP TABLE IF EXISTS test3;
CREATE TABLE test3(b int);
INSERT INTO test3 VALUES (400),(500),(600);
遊標定義
遊標(Cursor)是處理數據的一種方法,爲了查看或者處理結果集中的數據,遊標提供了在結果集中一次一行遍歷數據的能力。spa
遊標只能在存儲過程和函數中使用。3d
遊標的做用
如sql:
select a,b from test1;
上面這個查詢返回了test1中的數據,若是咱們想對這些數據進行遍歷處理,此時咱們就能夠使用遊標來進行操做。
遊標至關於一個指針,這個指針指向select的第一行數據,能夠經過移動指針來遍歷後面的數據。
遊標的使用步驟
聲明遊標:這個過程只是建立了一個遊標,須要指定這個遊標須要遍歷的select查詢,聲明遊標時並不會去執行這個sql。
打開遊標:打開遊標的時候,會執行遊標對應的select語句。
遍歷數據:使用遊標循環遍歷select結果中每一行數據,而後進行處理。
關閉遊標:遊標使用完以後必定要關閉。
遊標語法
聲明遊標
DECLARE 遊標名稱 CURSOR FOR 查詢語句;
一個begin end中只能聲明一個遊標。
打開遊標
open 遊標名稱;
遍歷遊標
fetch 遊標名稱 into 變量列表;
取出當前行的結果,將結果放在對應的變量中,並將遊標指針指向下一行的數據。
當調用fetch的時候,會獲取當前行的數據,若是當前行無數據,會引起mysql內部的NOT FOUND
錯誤。
關閉遊標
close 遊標名稱;
遊標使用完畢以後必定要關閉。
單遊標示例
寫一個函數,計算test1表中a、b字段全部的和。
建立函數:
/*刪除函數*/
DROP FUNCTION IF EXISTS fun1;
/*聲明結束符爲$*/
DELIMITER $
/*建立函數*/
CREATE FUNCTION fun1(v_max_a int)
RETURNS int
BEGIN
/*用於保存結果*/
DECLARE v_total int DEFAULT 0;
/*建立一個變量,用來保存當前行中a的值*/
DECLARE v_a int DEFAULT 0;
/*建立一個變量,用來保存當前行中b的值*/
DECLARE v_b int DEFAULT 0;
/*建立遊標結束標誌變量*/
DECLARE v_done int DEFAULT FALSE;
/*建立遊標*/
DECLARE cur_test1 CURSOR FOR SELECT a,b from test1 where a<=v_max_a;
/*設置遊標結束時v_done的值爲true,能夠v_done來判斷遊標是否結束了*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=TRUE;
/*設置v_total初始值*/
SET v_total = 0;
/*打開遊標*/
OPEN cur_test1;
/*使用Loop循環遍歷遊標*/
a:LOOP
/*先獲取當前行的數據,而後將當前行的數據放入v_a,v_b中,若是當前行無數據,v_done會被置爲true*/
FETCH cur_test1 INTO v_a, v_b;
/*經過v_done來判斷遊標是否結束了,退出循環*/
if v_done THEN
LEAVE a;
END IF;
/*對v_total值累加處理*/
SET v_total = v_total + v_a + v_b;
END LOOP;
/*關閉遊標*/
CLOSE cur_test1;
/*返回結果*/
RETURN v_total;
END $
/*結束符置爲;*/
DELIMITER ;
上面語句執行過程當中可能有問題,解決方式以下。
錯誤信息:Mysql 建立函數出現This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary
mysql的設置默認是不容許建立函數
解決辦法1:
執行:
SET GLOBAL log_bin_trust_function_creators = 1;
不過 重啓了 就失效了
注意: 有主從複製的時候 從機必需要設置 否則會致使主從同步失敗
解決辦法2:
在my.cnf裏面設置
log-bin-trust-function-creators=1
不過這個須要重啓服務
見效果:
mysql> SELECT a,b FROM test1;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 3 | 4 |
| 5 | 6 |
+------+------+
3 rows in set (0.00 sec)
mysql> SELECT fun1(1);
+---------+
| fun1(1) |
+---------+
| 3 |
+---------+
1 row in set (0.00 sec)
mysql> SELECT fun1(2);
+---------+
| fun1(2) |
+---------+
| 3 |
+---------+
1 row in set (0.00 sec)
mysql> SELECT fun1(3);
+---------+
| fun1(3) |
+---------+
| 10 |
+---------+
1 row in set (0.00 sec)
遊標過程詳解
以上面的示例代碼爲例,我們來看一下游標的詳細執行過程。
遊標中有個指針,當打開遊標的時候,纔會執行遊標對應的select語句,這個指針會指向select結果中第一行記錄。
當調用fetch 遊標名稱
時,會獲取當前行的數據,若是當前行無數據,會觸發NOT FOUND
異常。
當觸發NOT FOUND
異常的時候,咱們能夠使用一個變量來標記一下,以下代碼:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=TRUE;
當遊標無數據觸發NOT FOUND
異常的時候,將變量v_down
的值置爲TURE
,循環中就能夠經過v_down
的值控制循環的退出。
若是當前行有數據,則將當前行數據存到對應的變量中,並將遊標指針指向下一行數據,以下語句:
fetch 遊標名稱 into 變量列表;
嵌套遊標
寫個存儲過程,遍歷test二、test3,將test2中的a字段和test3中的b字段任意組合,插入到test1表中。
建立存儲過程:
/*刪除存儲過程*/
DROP PROCEDURE IF EXISTS proc1;
/*聲明結束符爲$*/
DELIMITER $
/*建立存儲過程*/
CREATE PROCEDURE proc1()
BEGIN
/*建立一個變量,用來保存當前行中a的值*/
DECLARE v_a int DEFAULT 0;
/*建立遊標結束標誌變量*/
DECLARE v_done1 int DEFAULT FALSE;
/*建立遊標*/
DECLARE cur_test1 CURSOR FOR SELECT a FROM test2;
/*設置遊標結束時v_done1的值爲true,能夠v_done1來判斷遊標cur_test1是否結束了*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done1=TRUE;
/*打開遊標*/
OPEN cur_test1;
/*使用Loop循環遍歷遊標*/
a:LOOP
FETCH cur_test1 INTO v_a;
/*經過v_done1來判斷遊標是否結束了,退出循環*/
if v_done1 THEN
LEAVE a;
END IF;
BEGIN
/*建立一個變量,用來保存當前行中b的值*/
DECLARE v_b int DEFAULT 0;
/*建立遊標結束標誌變量*/
DECLARE v_done2 int DEFAULT FALSE;
/*建立遊標*/
DECLARE cur_test2 CURSOR FOR SELECT b FROM test3;
/*設置遊標結束時v_done1的值爲true,能夠v_done1來判斷遊標cur_test2是否結束了*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done2=TRUE;
/*打開遊標*/
OPEN cur_test2;
/*使用Loop循環遍歷遊標*/
b:LOOP
FETCH cur_test2 INTO v_b;
/*經過v_done1來判斷遊標是否結束了,退出循環*/
if v_done2 THEN
LEAVE b;
END IF;
/*將v_a、v_b插入test1表中*/
INSERT INTO test1 VALUES (v_a,v_b);
END LOOP b;
/*關閉cur_test2遊標*/
CLOSE cur_test2;
END;
END LOOP;
/*關閉遊標cur_test1*/
CLOSE cur_test1;
END $
/*結束符置爲;*/
DELIMITER ;
見效果:
mysql> DELETE FROM test1;
Query OK, 9 rows affected (0.00 sec)
mysql> SELECT * FROM test1;
Empty set (0.00 sec)
mysql> CALL proc1();
Query OK, 0 rows affected (0.02 sec)
mysql> SELECT * from test1;
+------+------+
| a | b |
+------+------+
| 100 | 400 |
| 100 | 500 |
| 100 | 600 |
| 200 | 400 |
| 200 | 500 |
| 200 | 600 |
| 300 | 400 |
| 300 | 500 |
| 300 | 600 |
+------+------+
9 rows in set (0.00 sec)
成功插入了9條數據。
總結
- 遊標用來對查詢結果進行遍歷處理
- 遊標的使用過程:聲明遊標、打開遊標、遍歷遊標、關閉遊標
- 遊標只能在存儲過程和函數中使用
- 一個begin end中只能聲明一個遊標
- 掌握單個遊標及嵌套遊標的使用
- 你們下去了多練習一下,熟練掌握遊標的使用
Mysql系列目錄
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933257&idx=1&sn=0f0086a2465a2fcae13d3fea65064803&chksm=88621bb7bf1592a1ac94fe4107ba1ef26a0fa97e1bf9aea7279009d8bd240f1ef7d27aa10393&token=1876080189&lang=zh_CN#rd">第1篇:mysql基礎知識</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933270&idx=1&sn=409080e17352da2035b0bfdf63ccdfde&chksm=88621ba8bf1592beb2ef6106d6bf9f3eccd48d6814c7031f36e3c8be68821f17cf065129688c&token=1876080189&lang=zh_CN#rd"> 第2篇:詳解mysql數據類型(重點)</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933279&idx=1&sn=f8591b95362cb3c352d895b1289d665a&chksm=88621ba1bf1592b72a43a62e3f310695e8b87f17932d052145622c3edbb70ef8cb987849fc3e&token=516655478&lang=zh_CN#rd"> 第3篇:管理員必備技能(必須掌握)</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933289&idx=1&sn=c4f212c312ea86e08ad322caddd05e38&chksm=88621b97bf159281156ee3be510a1a15234531d2c97d66957e67377829ab23779809ea55bbde&token=1484565200&lang=zh_CN#rd"> 第4篇:DDL常見操做</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933296&idx=1&sn=1c56256d60c5847a944d87c8cfc9c14d&chksm=88621b8ebf159298b0789e2994d2aaf8b582effc7d8c1ba715deaca11c86a9dc8ac730878dc0&token=2000571846&lang=zh_CN#rd"> 第5篇:DML操做彙總(insert,update,delete)</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933300&idx=1&sn=bedef4d430dc76141e42e42ef6acfaa6&chksm=88621b8abf15929caae7904019c946a396885a33855ca465bacdd4187538005ebc3c116888f5&token=1814800041&lang=zh_CN#rd"> 第6篇:select查詢基礎篇</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933305&idx=1&sn=2c5ba0bea6fcdd57d86cecd63541f91a&chksm=88621b87bf1592915086c1e945119fcc95af6aa1127b90ef1b56b018083bfd787ad95efde918&token=1144227002&lang=zh_CN#rd"> 第7篇:玩轉select條件查詢,避免採坑</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933309&idx=1&sn=0f7dfec8bc70e67daa7159ee219325b8&chksm=88621b83bf1592951d949179061f39a1f4266b2879bc9a25af4da3b4b29f69ab1fcc595a462f&token=516674265&lang=zh_CN#rd"> 第8篇:詳解排序和分頁(order by & limit)</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933315&idx=1&sn=4abf2b34a53a85cbd4a3b9ee31fcd398&chksm=88621bfdbf1592eb6a5a13202588dde9068ac7e6391d8dbf3fde33647bf0e044839ba4228216&token=1937580929&lang=zh_CN#rd"> 第9篇:分組查詢詳解(group by & having)</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933321&idx=1&sn=110f6cacb90845bf2327fbcd7acd708c&chksm=88621bf7bf1592e1f1c0f2f01e40d4bd63a48d98daa4ba1157ecad4c6c6520d18b4b2c24c906&token=1096041061&lang=zh_CN#rd"> 第10篇:經常使用的幾十個函數詳解</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933325&idx=1&sn=33274227db275a3570e1e43ccdd4f49c&chksm=88621bf3bf1592e5b75f537e21961c4295fafb782dbf31c0c1cbf9e36f5f4ed44d31cdad68b3&token=1832579722&lang=zh_CN#rd"> 第11篇:深刻了解鏈接查詢及原理</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933342&idx=2&sn=2e41daa0926a9c32d5fddd23590391aa&chksm=88621be0bf1592f66904a184858df7c11129e8b545c7626b8b6c1fcc32d3dfdd9ab21aeda8e5&token=386795745&lang=zh_CN#rd"> 第12篇:子查詢</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933349&idx=1&sn=6e81f9046119cda43f8eb602d1139ef0&chksm=88621bdbbf1592cd9a20ec4715fe9f9459d079b641b04f607999c106cd52453d8c8508d939d7&token=386795745&lang=zh_CN#rd"> 第13篇:細說NULL致使的神坑,讓人防不勝防</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933355&idx=1&sn=b426ad28dfc2a64bba813df5b7c341a4&chksm=88621bd5bf1592c3c08e441398f699d0a4c2303a51519aac169447f22765cc613dfc3d991f8b&token=385335213&lang=zh_CN#rd"> 第14篇:詳解事務</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933370&idx=1&sn=4fe9b8e2aba766988c503737d34d9836&chksm=88621bc4bf1592d2b06d659884bf9881bd207a042ac36176f12808bd72f235e8e3404366259e&token=84059034&lang=zh_CN#rd"> 第15篇:詳解視圖</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933374&idx=1&sn=c294b6a69564a4c98d4c0cb29aeb9ac0&chksm=88621bc0bf1592d650752c44ca50540c1fa0c88c0a514019f1317559e13098de7dac37ddfc05&token=1531009350&lang=zh_CN#rd"> 第16篇:變量詳解</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933382&idx=1&sn=4cf80b4f50c80dcc8171d2128b47cf63&chksm=88621c38bf15952e193177a0ba3e03beeaeed996553ce6900f91518310332e99c915e8be2566&token=1341741305&lang=zh_CN#rd"> 第17篇:存儲過程&自定義函數詳解</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933388&idx=1&sn=59cb1d23845e45894bb72c1e2479f074&chksm=88621c32bf1595241573e4194912ca60a51eb8477f4b49492e26668c9bebc032e9d6672e7fdd&token=1832749573&lang=zh_CN#rd"> 第18篇:流程控制語句</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933392&idx=1&sn=ff29e380b42a0aa7cb1dc7659d745686&chksm=88621c2ebf1595380f99d9c4c89581638a27a5cf356de35d31aa9ae7ac17e63abe0e4adc813c&token=1479782197&lang=zh_CN#rd"> 第19篇:遊標詳解</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933396&idx=1&sn=b6cc5d5287bf43d94e6706fa217aa8cb&chksm=88621c2abf15953c3200c6d4d945ad70bdd2177f020f8e2229ae269153bbc8bf251af83e1135&token=1846211483&lang=zh_CN#rd"> 第20篇:異常捕獲及處理詳解</a>
- <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933400&idx=1&sn=61af771f10342ee4956efea6749abd71&chksm=88621c26bf15953041a6bc65734edf788af711ff176ad36884fe6411e5c4cfd0bf967e0e33fc&token=877024264&lang=zh_CN#rd">第21篇:什麼是索引?</a>
mysql系列大概有20多篇,喜歡的請關注一下,歡迎你們加我微信itsoku或者留言交流mysql相關技術!
原文出處:https://www.cnblogs.com/itsoku123/p/11642552.html