【Mysql 存储过程 Or 存储函数 傻傻分不清? 】

MySQL的存储函数(自定义函数)和存储过程都是用于存储SQL语句的。但是什么时候用什么呢?是不是总是傻傻的分不清? 本文来详细的讲一下存储函数 和存储过程 ,以后再也不会迷糊。

一、 异同点

MySQL的存储过程和函数都是一系列SQL语句的集合,调用时一次性执行这些SQL语句。但是它们有一些不同之处:

  1. 存储过程没有返回值,而函数有一个返回值.
  2. 存储过程可以在单个存储过程中执行一系列SQL语句,而自定义函数有诸多限制.
  3. 存储过程可以返回多个值,而函数只能有一个返回值.
  4. 存储过程实现较为复杂,自定义函数针对性强
  5. 存储函数只能有输入参数,而且不能带in, 而存储过程可以有多个in,out,inout参数。
  6. 存储过程可以调用存储函数、但函数不能调用存储过程。
名称 创建 调用 返回 应用
存储函数 create function select 只能是一个 计算字段值、处理数据、触发器(一般用于查询结果为一个值并有返回结果的)
存储过程 create procedure call 可以是多个也可以为空 1.复杂的业务逻辑,例如银行转账、订单处理;2.批量操作,例如批量插入、更新、删除数据;3.安全性控制,例如限制用户访问某些数据或执行某些操作(一般用于更新)

二、 存储函数

存储函数(自定义函数)是一种对MySQL扩展的途径,其用法与内置的函数相同。

语法

创建

CREATE FUNCTION 函数名([func_parameter[...]])

RETURNS type

[characteristic ...]

BEGIN

函数体

-- sql语句

END

函数名:表示存储函数的名称;

func_parameter:表示存储函数的参数列表,指定参数为IN、OUT或INOUT只对PROCEDURE是合法的,FUNCTION中总是默认为IN参数。

RETURNS type:语句表示函数返回数据的类型;

characteristic:创建函数时指定的对函数的约束。

func_parameter :由参数名称和参数类型组成。

函数体:函数主体,包含函数逻辑和SQL语句.

示例:

java 复制代码
delimiter $$
CREATE FUNCTION avg_salary(p_name VARCHAR(50))

RETURNS FLOAT

BEGIN

    DECLARE avg_age FLOAT;

    DECLARE total_salary FLOAT;

    DECLARE num_employees INT;

    DECLARE cur CURSOR FOR SELECT age FROM employees WHERE name = p_name;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET num_employees = 0;

    OPEN cur;

    FETCH cur INTO avg_age;

    CLOSE cur;



    SELECT AVG(salary) INTO total_salary FROM employees WHERE name = p_name;



    RETURN total_salary / avg_age;

end $$

delimiter ;

上述示例存储函数接受一个参数p_name,表示要查询的员工姓名。它首先声明了三个变量:avg_age、total_salary和num_employees。然后,它使用游标遍历employees表中与指定名称匹配的所有行,并计算这些行中的平均年龄。最后,它返回总薪水除以平均年龄的结果。

java 复制代码
> delimiter 是分隔符的意思 DELIMITER xx
> -- 示例:
>  DELIMITER $$   -- 指定 $$ 为分隔符
>  DELIMITER //   -- 指定 // 为分隔符 
>  DELIMITER ;    -- 指定 ; 为分隔符

调用

SELECT func_name()

调用函数名。

查看

查看定义: show create function func_name; 查看状态:show function status like 'func_name';

修改

ALTER FUNCTION function_name(parameters) [characteristic ...];

删除

DROP FUNCTION func_name

删除函数的语法只需写上函数名即可,函数的参数可以不用写出来。


三、 存储过程

存储过程是一组为了完成特定功能的SQL语句集合,经编译后存储在服务器端的数据库中,利用存储过程可以加速SQL语句的执行 存储过程的优点是可以提高运行效率,且使用存储过程的系统更加稳定。 存储过程的缺点是维护性较差,相对于简单SQL,存储过程的编写和调试都比较困难。

语法

创建 存储过程的创建步骤需要以下几步:

  1. 声明存储过程的名称和参数列表。
  2. 编写存储过程的主体部分,包括一系列SQL语句。
  3. 结束存储过程的主体部分,并指定返回值类型。
  4. 调用存储过程,传递参数并获取返回结果。

create procedure 存储过程名 ([params])

BEGIN

存储过程体(一组合法的SQL语句)

END

参数列表(params):如果有多个参数则用逗号 , 分隔开,一个参数包括三部分:参数模式、参数名、参数类型,如:in name varchar(20)。参数模式有:in 输入、out 输出、inout 输入输出参数。

关于IN | OUT | INOUT的详情如下:

IN :表示输入参数;它必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值。仅需要将数据传入存储过程,并不需要返回计算后的该值。只能当做传入参数

OUT: 表示输出参数;该值可在存储过程内部被改变,并可返回。不接受外部传入的数据,仅返回计算之后的值。只能当做转出参数。也就是说,即使传值给 OUT 参数,该参数也无法得到你传的值,得到的会是一个 null 值。

INOUT 表示既可以输入也可以输出;该参数即可作为输入,又可做为输出,也就是该参数既需要传入值,又可以返回值。可当做传入转出参数

示例:

java 复制代码
CREATE PROCEDURE GetEmployeeDetails(IN employeeID INT)

BEGIN

    SELECT * FROM employees WHERE ID = employeeID;

END;

上述示例为一个名为GetEmployeeDetails的存储过程,接受一个整型参数employeeID,用于查询员工详情。在存储过程中,使用SELECT语句从employees表中查询employeeID对应的记录。最后,通过END关键字结束存储过程的主体部分。

调用

使用 call 关键字来调用存储过程

call func_name([ proc_parameter [,proc_parameter ...]])

当无参数时,可以省略括号,不写;

当有参数时,不可省略括号。

查看

查看定义: show create procedurefunc_name; 查看状态:show procedurestatus like 'func_name';

修改

alter procedure sp_name [characteristic ...]

删除

drop procedure sp_name;

其中characteristic的取值为:

说明
language sql 说明routine_body部分是由SQL语句组成的,当前系统支持的语言为SQL
[not] deterministic 指明存储过程执行的结果是否确定。DETERMINISTIC 表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。
{contains sql / no sql / reads sql data / modifies sql data} 指明子程序使用SQL语句的限制。CONTAINS SQL表明子程序包含SQL语句,但是不包含读写数据的语句;NO SQL表明子程序不包含SQL语句;READS SQL DATA:说明子程序包含读数据的语句;MODIFIES SQL DATA表明子程序包含写数据的语句。默认情况下,系统会指定为CONTAINS SQL。
sql_security{definer/invoker} 指明谁有权限来执行。DEFINER 表示只有定义者才能执行;INVOKER 表示拥有权限的调用者可以执行。默认情况下,系统指定为DEFINER。
comment 'string' 注释信息,可以用来描述存储过程或函数
  如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏  🙌一起讨论
  你的评价就是我✍️创作的动力!					  💞💞💞
相关推荐
YashanDB1 小时前
【YashanDB知识库】XMLAGG方法的兼容
数据库·yashandb·崖山数据库
独行soc1 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍11基于XML的SQL注入(XML-Based SQL Injection)
数据库·安全·web安全·漏洞挖掘·sql注入·hw·xml注入
小林coding2 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
风间琉璃""2 小时前
bugkctf 渗透测试1超详细版
数据库·web安全·网络安全·渗透测试·内网·安全工具
drebander2 小时前
SQL 实战-巧用 CASE WHEN 实现条件分组与统计
大数据·数据库·sql
IvorySQL2 小时前
IvorySQL 4.0 发布:全面支持 PostgreSQL 17
数据库·postgresql·开源数据库·国产数据库·ivorysql
18号房客3 小时前
高级sql技巧进阶教程
大数据·数据库·数据仓库·sql·mysql·时序数据库·数据库架构
Dawnㅤ3 小时前
使用sql实现将一张表的某些字段数据存到另一种表里
数据库·sql
张声录13 小时前
【ETCD】【实操篇(十二)】分布式系统中的“王者之争”:基于ETCD的Leader选举实战
数据库·etcd
运维&陈同学3 小时前
【模块一】kubernetes容器编排进阶实战之基于velero及minio实现etcd数据备份与恢复
数据库·后端·云原生·容器·kubernetes·etcd·minio·velero