定义

  • 自定义函数和存储过程很类似,但是必须要有返回值。
  • 与内置的 sum()、max() 等 MySQL 原生函数使用方法类似。
    • select fun(val);
    • select * from t where col= fun(val);
  • 自定义函数可能在遍历每条记录中使用,注意性能损耗。

语法

  1. CREATE
  2. [DEFINER = { user | CURRENT_USER }]
  3. FUNCTION sp_name ([func_parameter[,...]])
  4. RETURNS type -- 必须有返回值
  5. [characteristic ...] routine_body
  6. func_parameter:
  7. param_name type
  8. type:
  9. Any valid MySQL data type
  10. characteristic:
  11. COMMENT 'string'
  12. | LANGUAGE SQL
  13. | [NOT] DETERMINISTIC
  14. | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  15. | SQL SECURITY { DEFINER | INVOKER }
  16. routine_body:
  17. Valid SQL routine statement
  18. -- 删除
  19. DROP FUNCTION fun_name;

示例

  1. -- 老师给的例子,还是阶乘,用自定义函数的方式
  2. mysql> delimiter //
  3. mysql>
  4. mysql> create function fun_test_1(total int)
  5. -> returns int
  6. -> begin
  7. -> declare i int;
  8. -> declare res int;
  9. -> set i := 1;
  10. -> set res := 1;
  11. -> if total <= 0 then
  12. -> set total := 1;
  13. -> end if;
  14. -> while i <= total do
  15. -> set res := res * i;
  16. -> set i := i + 1;
  17. -> end while;
  18. -> return res;
  19. -> end;//
  20. 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)
  21. -- 报错,提示因为函数的声明中没有"DETERMINISTIC, NO SQL, or READS SQL DATA"等关键字 ,需要使用打开参数 log_bin_trust_function_creators
  22. -- 解决方法,set global log_bin_trust_function_creators=1; 开启该选项可能会引起主从服务器不一致
  23. -- 或者 增加 上述相应功能的关键字
  24. -- 使用 deterministic 关键字
  25. -- 当你声明一个函数的返回是确定性的,则必须显示的使用deterministic关键字,默认是 no deterministic
  26. mysql> delimiter //
  27. mysql> create function fun_test_1(total int)
  28. -> returns int deterministic -- 这个只是告诉MySQL我这个函数是否会改变数据
  29. -- 即使我下面使用了insertupdateDML语句,MySQL不会检查
  30. -- 函数是否会改变数据,完全依赖创建函数的用户去指定的关键字
  31. -- 而非真的是否有修改数据
  32. -- 只是声明,而非约束
  33. -> begin
  34. -> declare i int;
  35. -> declare res int;
  36. -> set i := 1;
  37. -> set res := 1;
  38. -> if total <= 0 then
  39. -> set total := 1;
  40. -> end if;
  41. -> while i <= total do
  42. -> set res := res * i;
  43. -> insert into test_proc_1 values(i, res); -- 在自定义函数中,同样可以使用sql
  44. -- 并且该SQLinsert,其实和deterministic违背。
  45. -> set i := i + 1;
  46. -> end while;
  47. -> return res;
  48. -> end;//
  49. Query OK, 0 rows affected (0.01 sec)
  50. mysql> delimiter ;
  51. mysql> truncate table test_proc_1;
  52. Query OK, 0 rows affected (0.11 sec)
  53. mysql> select fun_test_1(6); -- return6的阶乘,720
  54. +---------------+
  55. | fun_test_1(6) |
  56. +---------------+
  57. | 720 |
  58. +---------------+
  59. 1 row in set (0.02 sec)
  60. mysql> select * from test_proc_1;
  61. +------+------+
  62. | a | b |
  63. +------+------+
  64. | 1 | 1 |
  65. | 2 | 2 |
  66. | 3 | 6 |
  67. | 4 | 24 |
  68. | 5 | 120 |
  69. | 6 | 720 | -- 使用了insert语句进行插入阶乘的历史记录
  70. +------+------+
  71. 6 rows in set (0.00 sec)
  72. -- 关键字简单说明
  73. -- DETERMINISTIC:当给定相同的输入,产生确定的结果
  74. -- NOT DETERMINISTIC:默认值,认为产生的结果是不确定的
  75. -- READS SQL DATA:只是读取SQL数据
  76. -- MODIFIES SQL DATA:会修改数据
  77. -- NO SQL:没有SQL遇见
  78. -- 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 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。