概述
自定义函数,顾名思义就是是MySQL中用户自定义的函数,用于执行特定的操作或计算,并返回一个结果。与内置函数不同,自定义函数是根据用户的需求自定义的,可以根据具体的业务需求来编写和调用。
自定义函数具有以下的优势:
- 提高代码的重用性:通过将一些常用的操作封装成函数,可以在多个地方重复使用,减少了代码的重复编写。
- 提高代码的可读性:将一些复杂的操作封装成函数,可以使主程序的逻辑更加清晰,易于理解。
- 提高代码的可维护性:当业务需求变化时,只需要修改函数的实现,而不需要修改调用函数的地方,降低了维护成本。
常见操作
创建自定义函数
基本语法
create function function_name ([parameter datatype[, ...]]) returns return_datatype [[not] deterministic] begin -- 函数的逻辑代码 -- 可以包含多条sql语句 return result_values end;
语法解释
- 第一行
create function
关键字后是指定的自定义函数名称和可选变量。 - 第二行为返回值的数据类型,可以是任何Mysql的有效类型。
- 第三行表示函数是否是确定性的,默认为非确定性。确定性函数是指在给定相同的输入参数时,总是返回相同的结果。
- 最后
begin … end
中间为函数的逻辑代码,可包含多条sql语句,直到return 返回值后,才会立即终止存储函数的执行。
自定义函数局部变量定义和赋值
局部变量的定义和赋值,在上一节有提到过,具体可查看:Mysql 变量的使用。
declare <变量名> <变量类型> default <默认值>; set <变量名>=<值>;
查看自定义函数
show function status;-- 查看所有的自定义函数 show create function <自定义函数名>;-- 查看指定自定义函数
删除自定义函数
删除是必修课,在任何一个DDL语句中都必须学习创建和删除,语法如下:
drop function [if exists] <自定义函数名>;
使用自定义函数
使用自定义函数和平时使用的内部函数一样,正常调用就行。
# 自定义加法函数 create function two_add(a int, b int) returns int deterministic begin declare result int; set result = a + b; return result; end; # 使用自定义的加法函数 select two_add(3,3); +--------------+ | two_add(3,3) | +--------------+ | 6 | +--------------+ select a, b, two_add(a, b) as c from (select 2 as a, 3 as b union all select 6 as a, 8 as b) as t1; +---+---+------+ | a | b | c | +---+---+------+ | 2 | 3 | 5 | | 6 | 8 | 14 | +---+---+------+
扩展-流程控制
当遇到复杂逻辑时,我们需要执行多个 SQL 操作,这时候就要用到流程控制,流程控制语句的作用就是控制存储过程中 SQL 语句的执行顺序。大概分为以下三类:
- 顺序结构:从上往下依次按照顺序执行。
- 分支结构:按条件进行选择执行,从两条或多条路径中选择一条执行。
- 循环结构:满足一定条件下,重复执行一组语句。
常见的语法有条件判断语句、循环语句和跳转语句,注意这些只用于存储过程和存储函数。
分支结构:if 和 case 语句
# if 分支语法 if 表达式1 then 操作1; [elseif 表达式2 then 操作2;] ... [else 操作n;] end if; # case 分支语法1 case 表达式 when 值1 then 操作1; when 值2 then 操作2; ... else 操作n end case; # case 分支语法2 case when 条件1 then 操作1; when 条件2 then 操作2; ... else 操作n; end case;
分支结构和select中的有点相似,只不过结尾要加if
或者case
,并且每一个操作后面都要分号。
循环结构:loop
、while
和 repeat
语句
在这里只介绍while
的用法,while
在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。
# 语法1 while 循环条件 do 循环体 操作语句 end while;
跳转语句:iterate
和leave
语句
[while_label:] while 循环条件 do 循环体 操作语句 iterate while_label leave while_label end while;
精选示例
判断一个数是否为偶数
# 定义是否偶数函数,返回布尔值1或0 create function is_even(num int) returns boolean deterministic begin declare even boolean; if num % 2 = 0 then set even = true; else set even = false; end if; return even; end; # 调用 select is_even(6) as a,is_even(13) as b; +------+------+ | a | b | +------+------+ | 1 | 0 | +------+------+
自定义等级划分函数
# 定义函数 create function customerlevel(credit decimal(10, 2)) returns varchar(20) deterministic begin declare level varchar(20); if credit > 50000 then set level = 'platinum'; elseif (credit <= 50000 and credit >= 10000) then set level = 'gold'; elseif credit < 10000 then set level = 'silver'; end if; return level; end; # 调用 select a,customerlevel(a) as b from (select floor(rand()*50000)+10000 as a union all select floor(rand()*50000)+50000 as a union all select floor(rand()*10000) as a) as t1 ; +-------+----------+ | a | b | +-------+----------+ | 53753 | platinum | | 62311 | platinum | | 6059 | silver | +-------+----------+
随机给娃取名
# 定义 create function generatename() returns varchar(3) charset utf8 deterministic begin declare frist varchar(2056) default '赵钱孙李周郑王冯陈楮卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闽席季麻强贾路娄危江童颜郭梅盛林刁锺徐丘骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫经裘缪干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁'; declare last varchar(2056) default '嘉懿煜城懿轩烨伟苑博伟泽熠彤鸿煊博涛烨霖烨华煜祺智宸正豪昊然明杰诚立轩立辉峻熙弘文熠彤鸿煊烨霖哲瀚鑫鹏致远俊驰雨泽烨磊晟睿天佑文昊修洁黎昕远航旭尧鸿涛伟祺轩越泽浩宇瑾瑜皓轩擎苍擎宇志泽睿渊楷瑞轩弘文哲瀚雨泽鑫磊梦琪忆之桃慕青问兰尔岚元香初夏沛菡傲珊曼文乐菱痴珊恨玉惜文香寒新柔语蓉海安夜蓉涵柏水桃醉蓝春儿语琴从彤傲晴语兰又菱碧彤元霜怜梦紫寒妙彤曼易南莲紫翠雨寒易烟如萱若南寻真晓亦向珊慕灵以蕊寻雁映易雪柳孤岚笑霜海云凝天沛珊寒云冰旋宛儿绿真盼儿晓霜碧凡夏菡曼香若烟半梦雅绿冰蓝灵槐平安书翠翠风香巧代云梦曼幼翠友巧听寒梦柏醉易访旋亦玉凌萱访卉怀亦笑蓝春翠靖柏夜蕾冰夏梦松书雪乐枫念薇靖雁寻春恨山从寒忆香觅波静曼凡旋以亦念露芷蕾千兰新波代真新蕾雁玉冷卉紫山千琴恨天傲芙盼山怀蝶冰兰山柏翠萱乐丹翠柔谷山之瑶冰露尔珍谷雪乐萱涵菡海莲傲蕾青槐冬儿易梦惜雪宛海之柔夏青亦瑶妙菡春竹修杰伟诚建辉晋鹏天磊绍辉泽洋明轩健柏煊昊强伟宸博超君浩子骞明辉鹏涛炎彬鹤轩越彬风华靖琪明诚高格光华国源宇晗昱涵润翰飞翰海昊乾浩博和安弘博鸿朗华奥华灿嘉慕坚秉建明金鑫锦程瑾瑜鹏经赋景同靖琪君昊俊明季同开济凯安康成乐语力勤良哲理群茂彦敏博明达朋义彭泽鹏举濮存溥心璞瑜浦泽奇邃祥荣轩'; declare frist_num int default length(frist) / 3; declare last_num int default length(last) / 3; declare return_str varchar(255) default ''; set return_str = concat(return_str, substring(frist, floor(1 + rand() * frist_num), 1)); set return_str = concat(return_str, substring(last, floor(1 + rand() * last_num), 1)); set return_str = concat(return_str, substring(last, floor(1 + rand() * last_num), 1)); return return_str; end; # 调用 select generatename(); +----------------+ | generatename() | +----------------+ | 丁辉寒 | +----------------+
可以将第一个return_str固定为指定的姓,剩下的两位随机生成,还有如果要生成四位的姓名,可以再加一个 return_str 变量,这样就可以随机给娃取名了。
随机生成手机号
# 定义 create function generatephone() returns char(11) charset utf8 deterministic begin declare front varchar(100) default '000,156,136,176,183,157,150'; declare behind char(10) default '0123456789'; declare phone char(11) default substring(front, 1 + (floor((rand() * 6)) * 4), 3); -- 从1开始 4n+1 共6次 declare i int default 1; declare len int default length(behind);-- 记录后面号码长度 while i <= 8 do set i = i + 1; set phone = concat(phone, substring(behind, floor(1 + rand() * len), 1));-- 合并前面取到的号码,根据后面号码一位位取并合并,满足8位后跳出 end while; return phone; end; # 调用 select generatephone(); +-----------------+ | generatephone() | +-----------------+ | 15663636107 | +-----------------+
随机生成指定长度的密码
# 定义 create function generatepwd(n int) returns varchar(255) charset utf8 deterministic begin declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789'; declare return_str varchar(255) default ''; declare i int default 0; while i < n do set return_str = concat(return_str, substring(chars_str, floor(1 + rand() * 62), 1)); set i = i + 1; end while; return return_str; end; # 调用 select generatepwd(30); +--------------------------------+ | generatepwd(30) | +--------------------------------+ | podmtwtsrfq5lljmhevmxjwxxzuqgs | +--------------------------------+ select a,generatepwd(30) as b from (select 1 as a union all select 2 as a union all select 3 as a) as t1; +---+--------------------------------+ | a | b | +---+--------------------------------+ | 1 | ph16j7rgwvzaw2dnahlnx7qhni3zbq | | 2 | jrcepatj3taxaooobizz08w0iirbqn | | 3 | uabfzvmxgjbuzz39rcynaimtwuwipt | +---+--------------------------------+
从随机生成指定长度的密码函数可见,想要生成单个或者批量都可以信手拈来,比之前使用查询实现的方法(Mysql 生成批量随机密码)简便了许多.
总结
自定义函数是MySQL中的一种强大的功能,可以根据业务需求自定义函数来执行特定的操作或计算。建议多自己操作实践一下,相信你一定会发现他的好处的。
参考资料
Mysql 变量的使用:https://blog.csdn.net/weixin_50357986/article/details/135282438
MySQL官方文档:https://dev.mysql.com/doc/refman/8.0/en/create-function.html
MySQL Tutoria:https://www.mysqltutorial.org/mysql-stored-procedure/mysql-stored-function/
Mysql 生成批量随机密码:https://blog.csdn.net/weixin_50357986/article/details/134123708