MySQL创建自定义函数需启用log_bin_trust_function_creators,否则报错1418;必须显式声明DETERMINISTIC/NO SQL/READS SQL DATA;函数内禁用INSERT/UPDATE/DELETE、SELECT...INTO及显式游标,仅支持子查询赋值;同名函数用OR REPLACE静默覆盖,调试需查mysql.proc表。

MySQL 创建自定义函数必须开启 log_bin_trust_function_creators
不设这个变量,CREATE FUNCTION 会直接报错 ERROR 1418 (HY000),哪怕你有 SUPER 权限。MySQL 默认禁止创建可能影响主从复制一致性的函数,而自定义函数默认被归为此类。
- 临时解决(重启失效):
SET GLOBAL log_bin_trust_function_creators = 1; - 永久生效:在
my.cnf的[mysqld]段落下加一行log_bin_trust_function_creators=1,然后重启 MySQL - 注意:如果启用了二进制日志(即主从或备份依赖 binlog),且函数非确定性(比如用
NOW()、RAND()、查询表数据),仍可能造成主从不一致——这不是权限问题,是设计约束
函数体里不能出现 SELECT … INTO 或显式游标
MySQL 自定义函数只允许返回单个值,且函数体内不能执行会返回结果集的语句。常见误写是想“查一条数据赋给变量”,结果写了 SELECT col INTO var FROM t WHERE id=1; —— 这语法本身合法,但前提是该语句必须出现在存储过程里,不是函数里。
- 函数中取值只能靠
SELECT ... INTO的变体:用子查询直接赋值,例如SET var = (SELECT col FROM t WHERE id=1 LIMIT 1); - 如果子查询没结果,
var会变成NULL,记得判空 - 不能有
INSERT/UPDATE/DELETE(除非函数声明为MODIFIES SQL DATA,但绝大多数场景不该这么干——函数应保持无副作用)
DETERMINISTIC / NO SQL / READS SQL DATA 必须显式声明
创建函数时必须指定特性,否则报错 ERROR 1418。MySQL 靠这个标记判断函数是否安全用于复制和查询优化,不是可选项。
- 纯计算、无外部依赖 → 用
DETERMINISTIC(如RETURN a + b;) - 完全不碰数据库 → 用
NO SQL(如RETURN UPPER(str);) - 只读表,不改数据 → 用
READS SQL DATA(如RETURN (SELECT name FROM user WHERE id = x);) - 千万别乱写
DETERMINISTIC却在函数里调NOW()或RAND(),这会导致主从数据不一致,而且 MySQL 不校验逻辑,只信你写的声明
函数名冲突会静默覆盖,且无法 ALTER FUNCTION
MySQL 不支持修改已有函数,CREATE FUNCTION 遇到同名函数会直接报错;但加上 OR REPLACE 就会覆盖——没有提示,不警告,旧逻辑彻底丢弃。
- 开发时建议统一加
OR REPLACE,避免反复删再建 - 上线前务必确认函数名未被其他业务占用(尤其公共库),名字太短如
fmt_date极易撞车 - 调试阶段别依赖
SHOW CREATE FUNCTION查源码——它不显示完整函数体(长度超限会被截断),得用SELECT body FROM mysql.proc WHERE name='xxx';(需对应权限)
SELECT 语句。上线前最好在真实数据量下压测单次调用耗时。










