Mysql 存储过程实例详解
存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,存储和和函数的区别在于函数必须有返回值,而存储过程没有,存储过程的参数可以使用IN、OUT、INOUT类型,而函数的参数只能是IN类型。存储过程再简单点来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批件,虽然它们的作用不仅限于批处理。在我看来, 存储过程就是有业务逻辑和流程的集合, 可以在存储过程中创建表,更新数据, 删除等等。本次博客就来讲一下存储过程
存储过程的操作
语法如下:
创建:
CREATE PROCEDURE sp_name([proc_parameter[,...]])
[characteristic...] routine_body proc_parameter:
[IN|OUT|INOUT] param_name type #type: Any valid MySQL data type
characteristic:
LANGUAGE SQL
|[NOT] DETERMINISTIC|{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}|SQL SECURITY {DEFINAER|INVOKER}|COMMENT 'string'
routine_body:
Valid SQL procedure statement or statements 修改:
ALTER PROCEDURE sp_name [characteristic...]
characteristic:
{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}|SQL SECURITY {DEFINAER|INVOKER}|COMMENT 'string' 调用:
CALL sp_name([parameter[,...]]) 删除:
DROP PROCEDURE sp_name 查看:
show PROCEDURE STATUS [like 'pattern']
SHOW CREATE PROCEDURE sp_name
MySQL的存储过程和函数中允许包含DDL语句,也允许在存储过程中执行提交或者回滚,但是存储过程和函数不允许执行LOAD DATA INFILE语句,存储过程和函数可以调用其他的过程或者函数。
插入小知识点@:
.用户变量:以"@"开始,形式为"@变量名"
用户变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效。
.全局变量:定义方式 set GLOBAL 变量名 或者 set @@global.变量名
对所有客户端生效,只有具有super权限才可以设置全局变量。
存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批件,虽然它们的作用不仅限于批处理。
在我看来, 存储过程就是有业务逻辑和流程的集合, 可以在存储过程中创建表,更新数据, 删除等等。
为什么要使用存储过程
- 通过把处理封装在容易使用的单元中,简化复杂的操作(正如前面例子所述)。
- 由于不要求反复建立一系列处理步骤,这保证了数据的完整性。如果所有开发人员和应用程序都使用同一(试验和测试)存储过程,则所使用的代码都是相同的。这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。
- 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。
users表如下:
创建存储过程,传入性别(男或女),显示对应性别的用户id,返回对应性别的人数(我的是在mysql front中操作):
#DELIMITER $$
CREATE PROCEDURE user_procedure(IN sex VARCHAR(2) character set utf8,OUT num INT)
BEGIN
SELECT id FROM users WHERE gender=sex;
SELECT FOUND_ROWS() INTO num;
END #$$
#DELIMITER ;
如果大家用的navicat版本,应该改成是:
DELIMITER $$
CREATE PROCEDURE user_procedure(IN sex VARCHAR(2) character set utf8,OUT num INT)
BEGIN
SELECT id FROM users WHERE gender=sex;
SELECT FOUND_ROWS() INTO num;
END $$
DELIMITER ;
上面记得中文字符字段,一定要设置编码:character set utf8,这里自己被坑了好久才觉悟过来...
调用
CALL user_procedure('女',@num);
select @num;
定义条件和处理
条件的定义和处理可以用来定义在处理过程中遇到问题时相应的处理步骤。
语法如下:
条件定义:
DECLARE condition_name CONDITION FOR condition_value condition_value:
SQLSTATE [VALUE] sqlstate_value
|mysql_error_code
条件处理:
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type:
CONTINUE|EXIT|UNDO condition_value:
SQLSTATE [VALUE] sqlstate_value
|condition_name|SQLWARNING|NOT FOUND|SQLEXCEPTION|mysql_error_code
继续用users表举个例子吧!
现在有数据如下:
(1)当没有进行条件处理的时候:
#delimiter $$
create procedure user_insert()
begin
set @x=1;
insert into users(id,gender,name) values(1,'男','常贵');
set @x=2;
insert into users(gender,name) values('女','大脚');
set @x=3;
END #$$
上面的例子可以看出,当插入id=1,主键重复了,直接退出了,并没有执行余下的语句,所以@x的值为1。
(2)可以对主键重复进行处理:
#delimiter $$
create procedure user_insert2()
begin
declare continue handler for sqlstate '' set @x2=1;
set @x=1;
insert into users(id,gender,name) values(3,'男','jack');
set @x=2;
insert into users(id,gender,name) values(1,'男','mary');
set @x=3;
end #$$
#delimiter ;
调用call user_insert2();
这次在调用存储过程的时候,并没有报错,而是在遇到主键重复的时候,会安装定义的continue去执行,所以继续向下执行。
condition_value的值可以是通过declare定义的condition_name,可以是SQLSTATE的值或者mysql_error_code的值会在是SQLWARNING、NOT FOUND、SQLEXCEPTION,这个3个值是3种定义好的错误类别,分别代表不同的含义:
SQLWARNING:是对所有以01开头的SQLSTATE代码的速记
NOT FOUND是对所有以02开头的SQLSTATE代码的速记
SQLEXCEPTION是对所有没有被SQLWARNING或者NOT FOUND捕获的SQLSTATE代码的速记。
以上的declare continue handler for sqlstate '23000' set @x2=1;也可以用以下几种方式来写:
#捕获mysql-error-code
declare continue handler for 1062 set @x2=1;
#事先定义condition_name
declare duplicatekey condition for sqlstate '23000';
declare continue handler for duplicatekey set @x2=1;
#捕获sqlexception
declare continue handler for sqlexception set @x2=1;
流程控制
mysql支持的流程控制有:IF、CASE、LOOP、LEAVE、ITERATE、REPEAT和WHILE语句。
1.IF
语法如下:
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list]...
[ELSE statement_list]
END IF
举例:求两个数的最大值
#DELIMITER $$
CREATE PROCEDURE compare(IN n1 INT,IN n2 INT)
BEGIN
SET @res=0;
IF n1 > n2 THEN
SET @res=n1;
ELSEIF n1 = n2 THEN
SET @res=n1;
ELSE
SET @res=n2;
END IF;
END #$$
#DELIMITER ;
调用后查询结果如下:
2.CASE语句
语法如下:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list]...
[ELSE statement_list]
END CASE
或者:
CASE
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list]...
[ELSE statement_list]
END CASE
我们将以上例子使用case来实现:
#DELIMITER $$
CREATE PROCEDURE compare2(IN n1 INT,IN n2 INT)
BEGIN
SET @res=0;
CASE
WHEN n1>n2 THEN
SET @res=n1;
WHEN n1=n2 THEN
SET @res=n1;
ELSE
SET @res=n2;
END CASE;
END #$$
#DELIMITER ;
测试:
3.LOOP和LEAVE语句
LOOP可以实现简单的循环,通常和LEAVE一起使用,LOOP语法如下:
[begin_label:]LOOP
statement_list
END LOOP[end_label]
我们还是以users表为例,当前users表按照 id desc 数据如下:
使用循环向里面插入100行数据:
#DELIMITER $$
CREATE PROCEDURE userinset()
BEGIN
SET @x=0;
ins: LOOP #标签为ins
SET @x=@x+1;
IF @x=100 THEN
LEAVE ins; #当@x=100的时候,则退出循环
END IF;
INSERT INTO users(name,gender) values('周伯通', '男');
END LOOP ins;
END #$$
#DELIMITER ;
测试:
call userinset();
select count(1) from users;
4.ITERATE语句
必须在循环中使用,作用是跳过当前循环的剩下的语句,直接进入下一轮循环,相当于一些高级语言中的continue。
只向表中插入奇数行:(仍以users为例):
#delimiter $$
CREATE PROCEDURE inserinfo()
BEGIN
set @x=1000103;
ins: LOOP
SET @x=@x+1;
IF @x=1000113 THEN
LEAVE ins;
ELSEIF mod(@x,2)=0 THEN
ITERATE ins;
END IF;
INSERT INTO users(id,name) VALUES(@x,'乔峰');
END LOOP ins;
END #$$
#delimiter ;
测试:call inserinfo();
5.REPEAT语句
有条件的循环控制语句,当满足条件的时候退出循环,语法如下:
[begin_label:]REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
举例:再在上面例子中插入10行:
#delimiter $$
CREATE PROCEDURE inserinfo2()
BEGIN
DECLARE x INT DEFAULT 9;
ins: REPEAT
SET x=x+1;
INSERT INTO users(name,gender) VALUES(x,'保密');
UNTIL x>18 END REPEAT; END #$$
#delimiter ;
调用:call inserinfo2();查看数据如下
[begin_lable:]WHILE search_condition DO
statement_list
END WHILE [end_label]
以上的例子如果用while来实现如下:
#delimiter $$
CREATE PROCEDURE inserinfo3()
BEGIN
DECLARE x INT DEFAULT 9;
ins: WHILE x<=18 DO
SET x=x+1;
INSERT INTO users(name,gender) VALUES(x,'女');
END WHILE;
END #$$
#delimiter ;
测试:call inserinfo3();
光标的使用
在存储过程和函数中,可以使用光标对结果进行循环的处理,语法如下:
声明光标:
DECLARE cursor_name CURSOR FOR select_statement
OPEN光标:
OPEN cursor_name
FETCH光标:
FETCH cursor_name INTO var_name[,var_name]...
CLOSE光标:
CLOSE cursor_name
举例:
还是以users表为例,好吧。夜深人静。。不早了,未完待续....
Mysql 存储过程实例详解的更多相关文章
- 9.SQL存储过程实例详解
本文用3个题目,从建立数据库到创建存储过程,详细讲解数据库的功能. 题目1 学校图书馆借书信息管理系统建立三个表:学生信息表:student 字段名称 数据类型 说明 stuID char(10) 学 ...
- SQL存储过程实例详解
本文用3个题目,从建立数据库到创建存储过程,详细讲解数据库的功能. 题目1 学校图书馆借书信息管理系统建立三个表: 学生信息表:student 字段名称 数据类型 说明 ...
- mysql触发器trigger 实例详解
mysql触发器trigger 实例详解 (转自 https://www.cnblogs.com/phpper/p/7587031.html) MySQL好像从5.0.2版本就开始支持触发器的功能 ...
- mysql数据库分区功能及实例详解
分区听起来怎么感觉是硬盘呀,对没错除了硬盘可以分区数据库现在也支持分区了,分区可以解决大数据量的处理问题,下面一起来看一个mysql数据库分区功能及实例详解 一,什么是数据库分区 前段时间写过一篇 ...
- MySQL数据库备份详解
原文:MySQL数据库备份详解 对于任何数据库来说,备份都是非常重要的 数据库复制不能取代备份的作用 比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据 ...
- linux基础-磁盘阵列(RAID)实例详解
磁盘阵列(RAID)实例详解 raid技术分类 软raid技术 硬raid技术 Raid和lvm的区别 为什么选择用raid RAID详解 RAID-0 RAID-1 RAID-5 Raid-10 R ...
- MySQL关闭过程详解和安全关闭MySQL的方法
MySQL关闭过程详解和安全关闭MySQL的方法 www.hongkevip.com 时间: -- : 阅读: 整理: 红客VIP 分享到: 红客VIP(http://www.hongkevip.co ...
- 转:【工欲善其事必先利其器】—Entity Framework实例详解
开始本篇文章之前,先说一下Entity Framework 6 Alpha1在NuGet中已可用,原文链接http://blogs.msdn.com/b/adonet/archive/2012/10/ ...
- Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
随机推荐
- spring生命周期流程图
Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...
- redis之一初识redis
本文主要围绕以下几点进行阐述: 1.什么是redis? 2.为什么要使用redis呢? 3.redis的一些基本配置 4.redis的缺点? 正文: 1.什么是redis? Redis是一款内存高速缓 ...
- 使用Lucene-Spatial实现集成地理位置的全文检索
Lucene通过Spatial包提供了对基于地理位置的全文检索的支持,最典型的应用场景就是:“搜索中关村附近1公里内的火锅店,并按远近排序”.使用Lucene-Spatial添加对地理位置的支持,和之 ...
- RSA实现JS前端加密,PHP后端解密
web前端,用户注册与登录,不能直接以明文形式提交用户密码,容易被截获,这时就引入RSA. 前端加密 需引入4个JS扩展文件,jsbn.js.prng4.js.rng.js和rsa.js. <h ...
- lombok的介绍及使用
参考:https://blog.csdn.net/motui/article/details/79012846 介绍 在项目中使用Lombok可以减少很多重复代码的书写.比如说getter/sette ...
- H264三种码率控制方法(CBR, VBR, CVBR)
CBR(Constant Bit Rate)是以恒定比特率方式进行编码,有Motion发生时,由于码率恒定,只能通过增大QP来减少码字大小,图像质量变差,当场景静止时,图像质量又变好,因此图像质量不稳 ...
- 课程三(Structuring Machine Learning Projects),第二周(ML strategy(2)) —— 1.Machine learning Flight simulator:Autonomous driving (case study)
[中文翻译] 为了帮助您练习机器学习的策略, 在本周我们将介绍另一个场景, 并询问您将如何行动.我们认为, 这个工作在一个机器学习项目的 "模拟器" 将给一个任务, 告诉你一个机器 ...
- .net core在Linux下获取AD域信息
.net core在Linux下获取AD域信息 .net Core 2.1.4 .net core现在System.DirectoryServices只支持Windows平台下使用. 参考: http ...
- MyBatis源码解析【7】接口式编程
前言 这个分类比较连续,如果这里看不懂,或者第一次看,请回顾之前的博客 http://www.cnblogs.com/linkstar/category/1027239.html 修改例子 在我们实际 ...
- vue-04-组件
1, 介绍 vue最强大的功能, 可以扩展html元素, 封装可充用的代码 在较高的层面, 组件是自定义元素, vue的编译器为他添加特殊功能, 在有些情况下, 组件也可以表现为用 ls 特性进行扩展 ...