MySQL的存储函数(自定义函数)和存储过程都是用于存储SQL语句的。但是什么时候用什么呢?是不是总是傻傻的分不清? 本文来详细的讲一下存储函数 和存储过程 ,以后再也不会迷糊。
一、 异同点
MySQL的存储过程和函数都是一系列SQL语句的集合,调用时一次性执行这些SQL语句。但是它们有一些不同之处:
- 存储过程没有返回值,而函数有一个返回值.
- 存储过程可以在单个存储过程中执行一系列SQL语句,而自定义函数有诸多限制.
- 存储过程可以返回多个值,而函数只能有一个返回值.
- 存储过程实现较为复杂,自定义函数针对性强
- 存储函数只能有输入参数,而且不能带in, 而存储过程可以有多个in,out,inout参数。
- 存储过程可以调用存储函数、但函数不能调用存储过程。
名称 | 创建 | 调用 | 返回 | 应用 |
---|---|---|---|---|
存储函数 | 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,存储过程的编写和调试都比较困难。
语法
创建 存储过程的创建步骤需要以下几步:
- 声明存储过程的名称和参数列表。
- 编写存储过程的主体部分,包括一系列SQL语句。
- 结束存储过程的主体部分,并指定返回值类型。
- 调用存储过程,传递参数并获取返回结果。
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' | 注释信息,可以用来描述存储过程或函数 |
如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏 🙌一起讨论 你的评价就是我✍️创作的动力! 💞💞💞