mysql 如何设置一个函数_MySQL学习笔记之MySQL自定义函数

一、什么是函数

函数存储着一系列sql语句,调用函数就是一次性执行这些语句。所以函数可以降低语句重复。【但注意的是函数注重返回值,不注重执行过程,所以一些语句无法执行。所以函数并不是单纯的sql语句集合。】

二、函数和存储过程的区别

关于存储过程,可以查看MySQL学习笔记之MySQL存储过程。

1)存储过程可以没有返回值,也可以有多个返回值,比较适合做批量插入、批量更新等操作

2)函数有且仅有一个返回值,比较适合做处理数据后返回一个结果

三、创建函数

语法:

create function 函数名([参数列表]) returns 返回类型

begin

函数体

end

参数格式:参数名 参数类型

四、调用函数

语法:select 函数名(参数列表)

五、系统变量log_bin_trust_function_creators

首先查看一个系统变量:log_bin_trust_function_creators

select @@log_bin_trust_function_creators;

mysql> select @@log_bin_trust_function_creators;

+-----------------------------------+

| @@log_bin_trust_function_creators |

+-----------------------------------+

| 0 |

+-----------------------------------+

1 row in set (0.00 sec)

变量说明:

当二进制日志启用后,这个变量就会启用。它控制是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为0(默认值),用户不得创建或修改存储函数,除非它们具有除CREATE ROUTINE或ALTER ROUTINE特权之外的SUPER权限。 设置为0还强制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性声明函数的限制。 如果变量设置为1,MySQL不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建。

当log_bin_trust_function_creators的值为0时创建存储函数将会报错:“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)”,如下:

mysql> delimiter $$

mysql> create function get_students_total() returns int

-> begin

-> declare total int default 0; # 定义total变量,默认值为0

-> select count(*) into total from students;

-> return total;

-> 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)

mysql> set @@global.log_bin_trust_function_creators = 1;

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter $$

mysql> create function get_students_total() returns int

-> begin

-> declare total int default 0;

-> select count(*) into total from students;

-> return total;

-> end $$

Query OK, 0 rows affected (0.02 sec)

mysql> select get_students_total();

+----------------------+

| get_students_total() |

+----------------------+

| 7 |

+----------------------+

1 row in set (0.06 sec)

那么为什么MySQL有这样的限制呢? 因为二进制日志的一个重要功能是用于主从复制,而存储函数有可能导致主从的数据不一致。

所以当开启二进制日志后,参数log_bin_trust_function_creators就会生效,限制存储函数的创建、修改、调用。

如何解决这个问题呢?

1)如果数据库没有使用主从复制,那么就可以将参数log_bin_trust_function_creators设置为1。

mysql> set @@global.log_bin_trust_function_creators = 1;

这个动态设置的方式会在服务重启后失效,所以我们还必须在my.cnf中设置,加上log_bin_trust_function_creators=1,这样就会永久生效。

2)明确指明函数的类型,如果我们开启了二进制日志, 那么我们就必须为我们的function指定一个参数。

其中下面几种参数类型里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。

这样一来相当于明确的告知MySQL服务器这个函数不会修改数据。

① DETERMINISTIC 不确定的

② NO SQL 没有SQl语句,当然也不会修改数据

③ READS SQL DATA 只是读取数据,当然也不会修改数据

④ MODIFIES SQL DATA 要修改数据

⑤ CONTAINS SQL 包含了SQL语句

mysql> delimiter $$

mysql> create function get_total() returns int reads sql data

-> begin

-> declare total int default 0;

-> select count(*) into total from students;

-> return total;

-> end $$

Query OK, 0 rows affected (0.08 sec)

mysql> delimiter ;

mysql> select get_total();

+-------------+

| get_total() |

+-------------+

| 7 |

+-------------+

1 row in set (0.09 sec)

六、存储函数使用示例

例1:创建存储函数,获取所有学生的总成绩

mysql> delimiter $$

mysql> create function get_students_totalScore() returns int reads sql data

-> begin

-> declare totalScore int default 0;

-> select sum(ifnull(t.总成绩,0)) into totalScore from students st left join (select s.student_id,sum(s.score) 总成绩 from subject su left join score s on su.id=s.subject_id group by s.student_id order by 总成绩 desc) t on st.id=t.student_id;

-> return totalScore;

-> end $$

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> select get_students_totalScore();

+---------------------------+

| get_students_totalScore() |

+---------------------------+

| 576 |

+---------------------------+

1 row in set (0.04 sec)

例2:创建存储函数根据传入的学生姓名,获取该学生的总成绩

mysql> delimiter $$

mysql> create function get_totalScore(name varchar(20)) returns int reads sql data

-> begin

-> declare totalScore int default 0;

-> select ifnull(t.总成绩,0) into totalScore from students st left join (select s.student_id,sum(s.score) 总成绩 from subject su left join score s on su.id=s.subject_id group by s.student_id order by 总成绩 desc) t on st.id=t.student_id where st.name=name;

-> return totalScore;

-> end $$

Query OK, 0 rows affected (0.06 sec)

mysql> delimiter ;

mysql> select get_totalScore('李四');

+--------------------------+

| get_totalScore('李四') |

+--------------------------+

| 268 |

+--------------------------+

1 row in set (0.06 sec)

七、查看存储函数

语法:show create function 函数名

mysql> show create function get_totalScore\G;

*************************** 1. row ***************************

Function: get_totalScore

sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `get_totalScore`(name varchar(20)) RETURNS int

READS SQL DATA

begin

declare totalScore int default 0;

select ifnull(t.总成绩,0) into totalScore from students st left join (select s.student_id,sum(s.score) 总成绩 from subject su left join score s on su.id=s.subject_id group by s.student_id order by 总成绩 desc) t on st.id=t.student_id where st.name=name;

return totalScore;

end

character_set_client: utf8mb4

collation_connection: utf8mb4_0900_ai_ci

Database Collation: utf8mb4_unicode_ci

1 row in set (0.00 sec)

八、删除存储函数

语法:drop function 函数名

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值