MySQL基础-存储过程与函数

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL基础-存储过程与函数

MySQL基础-存储过程与函数


MySQL从5.0版本开始支持存储过程和函数

存储过程和函数能够将复杂的SQL逻辑封装在一起,应用程序无须关注存储过程和函数内部复杂的SQL逻辑,而只需要简单地调用存储过程和函数即可


一、存储过程


1、概述

存储过程是一组经过 预先编译 的 SQL 语句的封装,预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行

  • 好处:
  1. 简化操作,提高了sql语句的重用性,减少了开发程序员的压力
  2. 减少操作过程中的失误,提高效率
  3. 减少网络传输量(客户端不需要把所有的 SQL 语句通过网络发给服务器)
  4. 减少了 SQL 语句暴露在网上的风险,也提高了数据查询的安全性


  • 和视图、函数的对比:
  1. 它和视图有着同样的优点,清晰、安全,还可以减少网络传输量;不过它和视图不同,视图是 虚拟表 ,通常不对底层数据表直接操作,而存储过程是程序化的 SQL,可以 直接操作底层数据表 ,相比于面向集合的操作方式,能够实现一些更复杂的数据处理
  2. 一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可;相较于函数,存储过程是 没有返回值 的


  • 存储过程的参数类型:

参数 IN 类型:输入参数(值)

参数 OUT 类型:输出参数(值)

参数 INOUT 类型:即输入又输出参数(值)

注意:IN、OUT、INOUT 都可以在一个存储过程中带多个或者没有


2、存储过程使用

  • 创建语法:
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
    存储过程体
END


  1. 形参类型可以是 MySQL数据库中的任意类型
  • characteristics 表示创建存储过程时指定的对存储过程的约束条件:
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'


  • characteristics取值说明:
LANGUAGE SQL :说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL
[NOT] DETERMINISTIC :指明存储过程执行的结果是否确定。DETERMINISTIC表示结果是确定
的。每次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为NOT DETERMINISTIC。
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } :指明子程序使
用SQL语句的限制。
CONTAINS SQL表示当前存储过程的子程序包含SQL语句,但是并不包含读写数据的SQL语句;
NO SQL表示当前存储过程的子程序中不包含任何SQL语句;
READS SQL DATA表示当前存储过程的子程序中包含读数据的SQL语句;
MODIFIES SQL DATA表示当前存储过程的子程序中包含写数据的SQL语句。
默认情况下,系统会指定为CONTAINS SQL。
SQL SECURITY { DEFINER | INVOKER } :执行当前存储过程的权限,即指明哪些用户能够执
行当前存储过程。
DEFINER 表示只有当前存储过程的创建者或者定义者才能执行当前存储过程;
INVOKER 表示拥有当前存储过程的访问权限的用户能够执行当前存储过程。  
COMMENT 'string' :注释信息,可以用来描述存储过程。


  1. 存储过程体中可以有多条 SQL 语句
1. BEGIN…END:BEGIN…END 中间包含了多个语句,每个语句都以(;)号为结束符。
2. DECLARE:DECLARE 用来声明变量,使用的位置在于 BEGIN…END 语句中间,而且需要在其他语句使用之前进行变量的声明。
3. SET:赋值语句,用于对变量进行赋值。
4. SELECT… INTO:把从数据表中查询的结果存放到变量中,也就是为变量赋值。


  1. 设置新的结束标记
DELIMITER 新的结束标记
#因为MySQL默认的语句结束符号为分号‘;’。为了避免与存储过程中SQL语句结束符相冲突,需要使用
#DELIMITER改变存储过程的结束符。


  • 示例:
DELIMITER $
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
    sql语句1;
    sql语句2;
END $
DELIMITER ;


  • CALL语句调用存储过程:
CALL 存储过程名(实参列表)


  • 设置变量输入输出值:
SET @name=值;
CALL sp1(@name);
SELECT @name;


  • 案例:创建存储过程show_mgr_name(),查询某个员工领导的姓名,并用INOUT参数“empname”输入员工姓名,输出领导的姓名
DELIMITER //
CREATE PROCEDURE show_mgr_name(INOUT lname VARCHAR(20))
BEGIN
    SELECT m.last_name INTO lname 
    FROM employees m
    WHERE m.employee_id = (
    SELECT e.employee_id 
    FROM employees e
    WHERE lname=e.last_name);
END //
DELIMITER ;

9eebda3dc8deabce070ca6b43e5edd4f.png

二、存储函数


1、概述

MySQL支持自定义函数,定义好之后,调用方式与调用MySQL预定义的系统函数一样

用户自己定义的存储函数与MySQL内部函数是一个性质的

区别在于,存储函数是 用户自己定义 的,而内部函数是MySQL的 开发者定义 的


2、存储函数使用

  • 创建语法:
CREATE FUNCTION 函数名(参数名 参数类型,...)
RETURNS 返回值类型
[characteristics ...]
BEGIN
    函数体 #函数体中肯定有 RETURN 语句
END


  • 说明:

1、参数列表:指定参数为IN、OUT或INOUT只对PROCEDURE是合法的,FUNCTION中总是默认为IN参数

2、RETURNS type 语句表示函数返回数据的类型,函数体必须包含一个 RETURN value 语句

3、characteristic 创建函数时指定的对函数的约束,取值与创建存储过程时相同

4、函数体也可以用BEGIN…END来表示SQL代码的开始和结束。如果函数体只有一条语句,也可以省略BEGIN…END

  • 调用存储函数:
SELECT 函数名(实参列表)


存储函数的使用方法与MySQL内部函数的使用方法是一样的,用户自己定义的存储函数与MySQL内部函数是一个性质的

  • 案例:创建存储函数count_by_id(),参数传入dept_id,该函数查询dept_id部门的员工人数,并返回,数据类型为整型
DELIMITER //
CREATE FUNCTION count_by_id(dept_id INT)
RETURNS INT
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT '查询部门平均工资'
BEGIN
RETURN (SELECT COUNT(*) 
  FROM employees 
  WHERE department_id = dept_id);
END //
DELIMITER ;


6f70e6d4a5761297ef0d3fd5a8fa7e27.png

注意:若在创建存储函数中报错“ you might want to use the less safe log_bin_trust_function_creators variable ”,有两种处理方法:

  • 方式1:加上必要的函数特性
“[NOT] DETERMINISTIC”和“{CONTAINS SQL | NO SQL | READS SQL DATA |MODIFIES SQL DATA}”


  • 方式2:
SET GLOBAL log_bin_trust_function_creators = 1;


三、查看修改删除


  • 使用SHOW CREATE语句查看创建信息 :
SHOW CREATE {PROCEDURE | FUNCTION} 存储过程名或函数名


  • 使用SHOW STATUS语句查看状态信息:
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']


  • 从information_schema.Routines表中查看存储过程和函数的信息:
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='存储过程或函数的名' [AND ROUTINE_TYPE = {'PROCEDURE|FUNCTION'}];


说明:如果在MySQL数据库中存在存储过程和函数名称相同的情况,最好指定ROUTINE_TYPE查询条件来指明查询的是存储过程还是函数


  • 使用ALTER语句实现修改相关特性 :
ALTER {PROCEDURE | FUNCTION} 存储过程或函数的名 [characteristic ...]


  • DROP语句删除存储过程和函数:
DROP {PROCEDURE | FUNCTION} [IF EXISTS] 存储过程或函数的名



四、存储过程与函数总结


1、对比

关键字 调用语法 返回值 应用场景
存储过 程 PROCEDURE CALL 存储过 程() 理解为有0个或 多个 一般用于更新
存储函 数 FUNCTION SELECT 函数 () 只能是一个 一般用于查询结果为一个值并 返回时


2、存储过程优缺点

  • 优点:

1、存储过程可以一次编译多次使用。存储过程只在创建时进行编译,之后的使用都不需要重新编译,这就提升了 SQL 的执行效率。

2、可以减少开发工作量。将代码 封装 成模块,实际上是编程的核心思想之一,这样可以把复杂的问题拆解成不同的模块,然后模块之间可以 重复使用 ,在减少开发工作量的同时,还能保证代码的结构清晰。

3、存储过程的安全性强。我们在设定存储过程的时候可以 设置对用户的使用权限 ,这样就和视图一样具有较强的安全性。

4、可以减少网络传输量。因为代码封装到存储过程中,每次使用只需要调用存储过程即可,这样就减少了网络传输量。

5、良好的封装性。在进行相对复杂的数据库操作时,原本需要使用一条一条的 SQL 语句,可能要连接多次数据库才能完成的操作,现在变成了一次存储过程,只需要 连接一次即可 。


  • 缺点:

1、可移植性差。存储过程不能跨数据库移植,比如在 MySQL、Oracle 和 SQL Server 里编写的存储过程,在换成其他数据库时都需要重新编写。

2、调试困难。只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。虽然也有一些第三方工具可以对存储过程进行调试,但要收费。

3、存储过程的版本管理很困难。比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。

4、它不适合高并发的场景。高并发的场景需要减少数据库的压力,有时数据库会采用分库分表的方式,而且对可扩展性要求很高,在这种情况下,存储过程会变得难以维护, 增加数据库的压力 ,显然就不适用了。

重新编写。

2、调试困难。只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。虽然也有一些第三方工具可以对存储过程进行调试,但要收费。

3、存储过程的版本管理很困难。比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。

4、它不适合高并发的场景。高并发的场景需要减少数据库的压力,有时数据库会采用分库分表的方式,而且对可扩展性要求很高,在这种情况下,存储过程会变得难以维护, 增加数据库的压力 ,显然就不适用了。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
存储 SQL 关系型数据库
MySQL基础:函数
本文介绍了MySQL中几种常用的内建函数,包括字符串函数、数值函数、日期函数和流程函数。字符串函数如`CONCAT()`用于拼接字符串,`TRIM()`用于去除字符串两端的空格,`MOD()`求余数,`RAND()`生成随机数,`ROUND()`四舍五入。日期函数如`CURDATE()`返回当前日期,`NOW()`返回当前日期和时间,`DATE_ADD()`添加时间间隔,`DATEDIFF()`计算日期差。流程函数如`IF()`和`CASE WHEN THEN ELSE END`用于条件判断。聚合函数如`COUNT()`统计行数,`SUM()`求和,`AVG()`求平均值
24 8
MySQL基础:函数
|
12天前
|
JSON 关系型数据库 MySQL
MySQL 8.0常用函数汇总与应用实例
这些函数只是MySQL 8.0提供的众多强大功能的一部分。通过结合使用这些函数,你可以有效地处理各种数据,优化数据库查询,并提高应用程序的性能和效率。
18 3
|
2月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 `RIGHT` 函数
【8月更文挑战第8天】
236 7
在 MySQL 中使用 `RIGHT` 函数
|
2月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 `REPLACE` 函数
【8月更文挑战第8天】
637 7
在 MySQL 中使用 `REPLACE` 函数
|
2月前
|
存储 SQL 关系型数据库
在 MySQL 中使用 `RTRIM` 函数
【8月更文挑战第8天】
142 8
在 MySQL 中使用 `RTRIM` 函数
|
2月前
|
缓存 关系型数据库 MySQL
在 MySQL 中使用 SPACE 函数
【8月更文挑战第5天】
102 3
在 MySQL 中使用 SPACE 函数
|
1月前
|
存储 关系型数据库 MySQL
MySQL MATCH 函数如何使用 WITH QUERY EXPANSION?
【9月更文挑战第2天】MySQL MATCH 函数如何使用 WITH QUERY EXPANSION?
30 0
|
2月前
|
存储 关系型数据库 MySQL
|
2月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
133 0
|
2月前
|
存储 JSON 关系型数据库
MySQL基础:函数
【8月更文挑战第19天】
17 0
下一篇
无影云桌面