定义
- 自定义函数和存储过程很类似,但是必须要有返回值。
- 与内置的 sum()、max() 等 MySQL 原生函数使用方法类似。
- select fun(val);
- select * from t where col= fun(val);
- 自定义函数可能在遍历每条记录中使用,注意性能损耗。
语法
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type -- 必须有返回值
[characteristic ...] routine_body
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
-- 删除
DROP FUNCTION fun_name;
示例
-- 老师给的例子,还是阶乘,用自定义函数的方式
mysql> delimiter //
mysql>
mysql> create function fun_test_1(total int)
-> returns int
-> begin
-> declare i int;
-> declare res int;
-> set i := 1;
-> set res := 1;
-> if total <= 0 then
-> set total := 1;
-> end if;
-> while i <= total do
-> set res := res * i;
-> set i := i + 1;
-> end while;
-> return res;
-> end;//
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
-- 报错,提示因为函数的声明中没有"DETERMINISTIC, NO SQL, or READS SQL DATA"等关键字 ,需要使用打开参数 log_bin_trust_function_creators
-- 解决方法,set global log_bin_trust_function_creators=1; 开启该选项可能会引起主从服务器不一致
-- 或者 增加 上述相应功能的关键字
-- 使用 deterministic 关键字
-- 当你声明一个函数的返回是确定性的,则必须显示的使用deterministic关键字,默认是 no deterministic的
mysql> delimiter //
mysql> create function fun_test_1(total int)
-> returns int deterministic -- 这个只是告诉MySQL我这个函数是否会改变数据
-- 即使我下面使用了insert,update等DML语句,MySQL不会检查
-- 函数是否会改变数据,完全依赖创建函数的用户去指定的关键字
-- 而非真的是否有修改数据
-- 只是声明,而非约束
-> begin
-> declare i int;
-> declare res int;
-> set i := 1;
-> set res := 1;
-> if total <= 0 then
-> set total := 1;
-> end if;
-> while i <= total do
-> set res := res * i;
-> insert into test_proc_1 values(i, res); -- 在自定义函数中,同样可以使用sql
-- 并且该SQL是insert,其实和deterministic违背。
-> set i := i + 1;
-> end while;
-> return res;
-> end;//
Query OK, 0 rows affected (0.01 sec)
mysql> delimiter ;
mysql> truncate table test_proc_1;
Query OK, 0 rows affected (0.11 sec)
mysql> select fun_test_1(6); -- return了6的阶乘,720
+---------------+
| fun_test_1(6) |
+---------------+
| 720 |
+---------------+
1 row in set (0.02 sec)
mysql> select * from test_proc_1;
+------+------+
| a | b |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 6 |
| 4 | 24 |
| 5 | 120 |
| 6 | 720 | -- 使用了insert语句进行插入阶乘的历史记录
+------+------+
6 rows in set (0.00 sec)
-- 关键字简单说明
-- DETERMINISTIC:当给定相同的输入,产生确定的结果
-- NOT DETERMINISTIC:默认值,认为产生的结果是不确定的
-- READS SQL DATA:只是读取SQL数据
-- MODIFIES SQL DATA:会修改数据
-- NO SQL:没有SQL遇见
-- CONTAINS SQL:包含SQL语句,但是没有读写语句,理论有select now()等
官方文档:https://dev.mysql.com/doc/refman/5.7/en/stored-programs-logging.html
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/lzcosc 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。