先展示一段完整的存储过程代码作为例子方便进行语法说明。代码如下:

--##########定义课程分享量存储过程######################
delimiter $$
DROP PROCEDURE IF EXISTS statisCourseShareCount;
CREATE PROCEDURE statisCourseShareCount(IN day varchar(32),IN month varchar(32))BEGINDECLARE d BOOLEAN DEFAULT FALSE;DECLARE course_id_value BIGINT(20) DEFAULT 0;DECLARE t_count_value BIGINT(20) DEFAULT 0;DECLARE search_table varchar(200);DECLARE param varchar(200);DECLARE existsFlat int default 0;DECLARE ownerMemberId BIGINT(20) DEFAULT 0;DECLARE tmpShopId BIGINT(20) DEFAULT 0;DECLARE tmpCategoryId BIGINT(20) DEFAULT 0;DECLARE tmpCategoryPath VARCHAR(100) DEFAULT '';DECLARE tmpSubjectId BIGINT(20) DEFAULT 0;DECLARE tmpCourseType INT(10) DEFAULT 0;DECLARE tmpClassId BIGINT(20) DEFAULT 0;DECLARE tmpGradeId BIGINT(20) DEFAULT 0;DECLARE tmpGradePath varchar(100) DEFAULT '';DECLARE paperCount INT(10) DEFAULT 0;DECLARE share_count_cursor CURSOR FOR SELECT * FROM course_share_count_view;DECLARE CONTINUE HANDLER FOR NOT FOUND SET d = TRUE;SET search_table = CONCAT('youke_course_share_',month);SET param = CONCAT("'",day,"'");SET @cursor_sql = CONCAT('CREATE VIEW course_share_count_view as select course_id,count(id) as t_count from ',search_table,' where DATE(create_date) = ',param,' group by course_id');select @cursor_sql;PREPARE stmt from @cursor_sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;OPEN share_count_cursor;read_loop: LOOPFETCH share_count_cursor INTO course_id_value,t_count_value;IF d THENLEAVE read_loop;ELSESET existsFlat = 0;select count(id) into existsFlat from youke_statis_course_summary where course_id = course_id_value LIMIT 1;IF existsFlat > 0 THENUPDATE youke_statis_course_summary set share_count = share_count + t_count_value where course_id = course_id_value;ELSE SET paperCount = 0;select OwerID,ShopId,CategoryId,CategoryPath,CourseType into ownerMemberId,tmpShopId,tmpCategoryId,tmpCategoryPath,tmpCourseType from himall_products where Id = course_id_value;select Id,CategoryId,CategoryPath into tmpClassId,tmpGradeId,tmpGradePath from himall_grades where MemberId = ownerMemberId;IF tmpCourseType = 1 THENselect count(Id) into paperCount from himall_paperlist where ProductId = course_id_value and `Delete` = 0;END IF;INSERT INTO youke_statis_course_summary(course_id,owner_member_id,shop_id,category_id,category_path,subject_id,course_type,class_id,grade_id,grade_path,share_count,paper_count) values(course_id_value,ownerMemberId,tmpShopId,tmpCategoryId,tmpCategoryPath,statisSplit(tmpCategoryPath,'|',2),tmpCourseType,tmpClassId,tmpGradeId,tmpGradePath,t_count_value,paperCount);END IF;END IF;END LOOP;CLOSE share_count_cursor;DROP VIEW course_share_count_view;END;$$

1.delimiter声明

delimiter的作用是改变执行语句的分号,比如delimiter $$,那么创建语句就是以$$为结尾构成一句完整的创建语句,而不是遇到分号就自动结束了。

2.删除存储过程,创建存储过程,IN,OUT, INOUT参数

创建存储过程之前必须执行一个删除操作,避免之前残留的代码影响创建过程。

DROP PROCEDURE IF EXISTS myProcedure;

存储过程运行传入多个输入、输出参数,输入参数使用IN修饰,输出参数使用OUT修饰,输入输出参数INOUT修饰。

输入参数使用:

CREATE PROCEDURE myProcedure(IN param1 varchar(32),IN param2 varchar(32))

BEGIN

...

END;

$$

调用存储过程传入参数

Call myProcedure(‘参数1’,’参数2’);

输出参数使用:

CREATE PROCEDURE myProcedure(IN input varchar(32),OUT output varchar(32))

BEGIN

...

END;

$$

调用存储过程:

set @myOutput=’我的输出’;

call myProcedure(‘我的输入’,@myOutput);

输入输出参数使用:

CREATE PROCEDURE myProcedure(INOUT inoutValue varchar(32))

BEGIN

...

END;

$$

调用存储过程:

set @myInout=’我的输入输出’;

Call myProcedure(@myInout);

3.声明变量的三种方式

A) DECLARE

这种方式定义的变量,语句的位置必须在begin下,同时要带上参数类型。

语句

begin

DECLARE tname VARCHAR(50);

赋值

set tname =‘XXX’;

另外需要注意的是使用这种方式声明变量,set语句必须在所有DECLARE语句之后,否则就会编译失败。例如

DECLARE a VARCHAR(50);

set a=’XXX’;

DECLARE b VARCHAR(50);

就会失败。

B) set

这种方式定义的变量,定义同时赋值,语句的位置可以任意出现,不需要带上参数类型,但定义的变量是会话变量,如果想定义局部变量,那么变量名加上'@'。

语句

set @aa='XXX';

C) select

性质同上一个set,但是这个可以通过插询记录去赋值

语句

select @var=cnm FROM tbnm;

set和select其实可以相互转化,下面两句是相同的

set @var=(select cnm FROM tbnm);

select @var=cnm FROM tbnm;

4.字符串拼接,动态表名和动态参数

存储过程中的SQL语句如果要使用动态表名或者动态参数的时候,需要利用预处理语句来实现。

首先讲解一个创建动态表的例子

  1. 声明一个对象存储动态表名

DECLARE comment_report_table VARCHAR(50);

2.使用字符串拼接函数生成动态表名;

SET comment_report_table = CONCAT("youke_comment_report_",month);

3.使用预处理语句创建动态表

SET @commentReportTableSQL = CONCAT('CREATE TABLE IF NOT EXISTS ',comment_report_table," (`id` bigint(20) NOT NULL AUTO_INCREMENT,`owner_shop_id` bigint(20) DEFAULT '0',`target_type` int(10) DEFAULT '0' COMMENT '1:课程,2:资源',`target_id` bigint(20) DEFAULT '0' COMMENT '目标id',`owner_id` bigint(20) DEFAULT '0',`member_id` bigint(20) DEFAULT '0',`good_comment` tinyint(1) DEFAULT '0' COMMENT '是否好评',`comment_score` bigint(20) DEFAULT '0' COMMENT '评分',`create_date` datetime DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;");PREPARE temp FROM @commentReportTableSQL;
EXECUTE temp;

5.游标、循环以及判断的整合使用

存储过程中有三种循环方式,WHILE、REPEAT和LOOP

WHILE循环的语法如下:

WHILE expression DO

Statements

END WHILE

WHILE循环在每次迭代开始时检查表达式。 如果expression为TRUE,MySQL将执行WHILE和END WHILE之间的语句,直到expression为FALSE。 WHILE循环称为预先测试条件循环,因为它总是在执行前检查语句的表达式。

REPEAT循环的语法如下:

REPEAT

statements;

UNTIL expression

END REPEAT

首先,MySQL执行语句,然后评估求值表达式(expression)。如果表达式(expression)的计算结果为FALSE,则MySQL将重复执行该语句,直到该表达式计算结果为TRUE。

因为REPEAT循环语句在执行语句后检查表达式(expression),因此REPEAT循环语句也称为测试后循环。

LOOP,LEAVE和ITERATE语句

有两个语句允许您用于控制循环:

LEAVE语句用于立即退出循环,而无需等待检查条件。LEAVE语句的工作原理就类似PHP,C/C++,Java等其他语言的break语句一样。

ITERATE语句允许您跳过剩下的整个代码并开始新的迭代。ITERATE语句类似于PHP,C/C++,Java等中的continue语句。

MySQL还有一个LOOP语句,它可以反复执行一个代码块,另外还有一个使用循环标签的灵活性。

以下是使用LOOP循环语句的示例。

CREATE PROCEDURE test_mysql_loop()BEGINDECLARE x  INT;DECLARE str  VARCHAR(255);SET x = 1;SET str =  '';loop_label:  LOOPIF  x > 10 THEN LEAVE  loop_label;END  IF;SET  x = x + 1;IF (x mod 2) THENITERATE  loop_label;ELSESET  str = CONCAT(str,x,',');END IF;END LOOP;    SELECT str;
END;游标的语法如下:
DROP PROCEDURE IF EXISTS text5;
CREATE PROCEDURE text5()BEGINDECLARE d BOOLEAN DEFAULT FALSE;DECLARE n INT;DECLARE cursor_names CURSOR FOR (SELECT BUY_COUNTFROM tb_ranking); -- 定义游标,并给游标赋值(集合)DECLARE CONTINUE HANDLER FOR NOT FOUND SET d = TRUE; -- 定义异常捕捉,当游标也没有可取的值时,done会进行捕捉,然后我们依次跳出循环OPEN cursor_names; -- 打开游标REPEATFETCH cursor_names INTO n; -- 取一条数据# 省略UNTIL !d END REPEAT;CLOSE cursor_names; -- 关闭游标END;

但是如果游标查询的是一个动态表名,就必须先创建一个视图,再用视图来定义游标才能实现游标的遍历功能。下面我们就用一段具体的代码来说明一下。

--##### 定义课程访问量存储过程 #####
delimiter $$
DROP PROCEDURE IF EXISTS statisCourseVisitCount;
CREATE PROCEDURE statisCourseVisitCount(IN day varchar(32),IN month varchar(32))BEGINDECLARE d BOOLEAN DEFAULT FALSE;DECLARE course_id_value BIGINT(20) DEFAULT 0;DECLARE t_count_value BIGINT(20) DEFAULT 0;DECLARE search_table varchar(200);DECLARE param varchar(200);DECLARE existsFlat int default 0;DECLARE ownerMemberId BIGINT(20) DEFAULT 0;DECLARE tmpShopId BIGINT(20) DEFAULT 0;DECLARE tmpCategoryId BIGINT(20) DEFAULT 0;DECLARE tmpCategoryPath VARCHAR(100) DEFAULT '';DECLARE tmpSubjectId BIGINT(20) DEFAULT 0;DECLARE tmpCourseType INT(10) DEFAULT 0;DECLARE tmpClassId BIGINT(20) DEFAULT 0;DECLARE tmpGradeId BIGINT(20) DEFAULT 0;DECLARE tmpGradePath varchar(100) DEFAULT '';DECLARE paperCount INT(10) DEFAULT 0;##利用视图定义游标DECLARE visit_count_cursor CURSOR FOR SELECT * FROM visit_count_view;##遍历停止判断DECLARE CONTINUE HANDLER FOR NOT FOUND SET d = TRUE;##拼接动态表名SET search_table = CONCAT('youke_course_visit_log_',month);SET param = CONCAT("'",day,"'");##创建视图的SQL语句SET @cursor_sql = CONCAT('CREATE VIEW visit_count_view as select course_id,count(id) as t_count from ',search_table,' where DATE(create_date) = ',param,' group by course_id');select @cursor_sql;##预处理视图的SQL语句PREPARE stmt from @cursor_sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;##开启游标OPEN visit_count_cursor;##遍历游标read_loop: LOOP##将遍历的结果赋值到变量中,注意顺序要一一对应FETCH visit_count_cursor INTO course_id_value,t_count_value;IF d THEN##没有更多数据跳出循环LEAVE read_loop;ELSESET existsFlat = 0;select count(id) into existsFlat from youke_statis_course_summary where course_id = course_id_value LIMIT 1;IF existsFlat > 0 THENUPDATE youke_statis_course_summary set visit_count = visit_count + t_count_value where course_id = course_id_value;ELSE SET paperCount = 0;select OwerID,ShopId,CategoryId,CategoryPath,CourseType into ownerMemberId,tmpShopId,tmpCategoryId,tmpCategoryPath,tmpCourseType from himall_products where Id = course_id_value;select Id,CategoryId,CategoryPath into tmpClassId,tmpGradeId,tmpGradePath from himall_grades where MemberId = ownerMemberId;IF tmpCourseType = 1 THENselect count(Id) into paperCount from himall_paperlist where ProductId = course_id_value and `Delete` = 0;END IF;INSERT INTO youke_statis_course_summary(course_id,owner_member_id,shop_id,category_id,category_path,subject_id,course_type,class_id,grade_id,grade_path,visit_count,paper_count) values(course_id_value,ownerMemberId,tmpShopId,tmpCategoryId,tmpCategoryPath,statisSplit(tmpCategoryPath,'|',2),tmpCourseType,tmpClassId,tmpGradeId,tmpGradePath,t_count_value,paperCount);END IF;END IF;
##关闭变量END LOOP;
##关闭游标CLOSE visit_count_cursor;
##删除视图DROP VIEW visit_count_view;END;$$

MySQL存储过程实战二:语法讲解。相关推荐

  1. MySQL 存储过程 经常使用语法

    MySQL 存储过程是从 MySQL 5.0 開始添加的新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装.特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库 ...

  2. mysql存储过程实战

    今天科比离去,今天肺炎病毒持续肆虐... 意识到生命的脆弱,今天我继续前行,比以往更加坚定和紧迫,这辈子不活好自己就算白来一趟. 最近需要用到mysql存储过程去处理一些表数据,然后利用java po ...

  3. Mysql函数:Last_insert_id()语法讲解

    Mysql函数可以实现许多我们需要的功能,下面介绍的Mysql函数Last_insert_id()就是其中之一,希望对您学习Mysql函数能有所帮助. 自动返回最后一个INSERT或 UPDATE 查 ...

  4. Mysql数据库存储过程基本语法讲解

    Mysql数据库存储过程基本语法讲解 一般情况下MYSQL以:结尾表示确认输入并执行语句,但在存储过程中:不是表示结束,因此可以用该命令将:号改为//表示确认输入并执行.存储过程如同一门程序设计语言, ...

  5. mysql存储过程语法 if_mysql存储过程语法 if

    MySql存储过程 MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程, ...

  6. Mysql 存储过程基本语法

    delimiter // 一般情况下MYSQL以:结尾表示确认输入并执行语句,但在存储过程中:不是表示结束,因此可以用该命令将:号改为//表示确认输入并执行. 一.创建存储过程 1.基本语法: cre ...

  7. Mysql存储过程基本语法

    Mysql 存储过程基本语法 转载自这篇文章 delimiter // 一般情况下MYSQL以:结尾表示确认输入并执行语句,但在存储过程中:不是表示结束,因此可以用该命令将:号改为//表示确认输入并执 ...

  8. MySQL 存储过程的基本用法

    http://database.51cto.com/art/201006/203159.htm 我们大家都知道MySQL 存储过程是从 MySQL 5.0 开始逐渐增加新的功能.存储过程在实际应用中也 ...

  9. mysql存储过程和自定义函数

    2019独角兽企业重金招聘Python工程师标准>>> 存储过程简介 SQL语句需要先编辑后执行,而存储过程是一组为了完成特定功能的SQL语句集,经编译后存储过程在数据库中,用户通过 ...

最新文章

  1. python字符串删除,列表删除以及字典删除的总结
  2. 基于深度学习的目标检测算法综述(一)
  3. nginx修改默认端口
  4. jupyter notebook的单独安装与使用
  5. hbase 页面访问_HBase在滴滴出行的应用场景和最佳实践
  6. ChaiNext:市场短期内延续区间震荡
  7. [No0000F5]C# 类(Class)
  8. 用wxpython编写登录界面_wxpython+pymysql实现用户登陆功能
  9. bzoj:2331: [SCOI2011]地板
  10. 关于使用UE编辑器无法初始化ftp的问题
  11. 剑侠世界手游服务器维护公告,剑侠世界手游公告_剑侠世界手游开服公告_更新公告_安趣网...
  12. win的反义词_小学英语常见的120对反义词大全,聪明的小升初家长快来收藏学习...
  13. import math java_java 中 Math类
  14. 易语言解析网页内容替换换行符问题
  15. VSCode中值得推荐的常用的33个高效前端插件「效率篇」(二)
  16. Win10下开机自动启动运行bat脚本并打开cmd运行命令
  17. SAP SM04踢人操作(摘录)
  18. uni-app转小程序遇到的问题 (组件使用插槽的问题)(跨端兼容、条件编译)(小程序自定义胶囊按钮封装)(uni-app挂载原型链)
  19. Android开发日志打卡APP(一)
  20. Python 数据分析之Numpy

热门文章

  1. Cadence 17.2 软件使用(2)— OrCAD新建原理图工程和原理图库
  2. 【VMware vSAN 7.0】5.4.2 创建 vSAN 集群
  3. Zynq-Linux移植学习笔记之49-国产ZYNQ适配国产裕太PHY网络调试
  4. java配置JAVA_HOME环境变量
  5. ServerGuide 引导安装指南
  6. 从PDF文件提取文本--pdflib TET库
  7. (附源码)计算机毕业设计ssm电影院订票系统
  8. 在Java中标签的使用
  9. Java 中标签的作用
  10. tpm2-tools相关实验