MySQL 自定义函数不能在普通用户权限下直接创建,必须拥有
CREATE ROUTINE权限,且默认情况下
log_bin_trust_function_creators为 OFF —— 这会导致创建失败并报错
ERROR 1418。
为什么执行 CREATE FUNCTION 报 ERROR 1418?
这是 MySQL 的安全限制:当二进制日志(binlog)启用时,系统要求确定性函数(DETERMINISTIC)、或显式声明为
READS SQL DATA/
NO SQL,否则拒绝创建。常见错误信息是:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled
解决方法不是简单加
DETERMINISTIC(它必须真实符合函数行为),而是按需选择以下之一: 如果函数确实不读写数据,加上
DETERMINISTIC或
NO SQL如果函数会查表,必须加
READS SQL DATA临时关闭校验(仅测试环境):
SET GLOBAL log_bin_trust_function_creators = 1
创建带参数和返回值的标量函数
MySQL 函数只能返回单个值(标量),不能返回结果集。定义时需明确指定参数类型、返回类型、特性子句。例如,写一个截取手机号后 4 位的函数:
DELIMITER $$ CREATE FUNCTION get_phone_tail(p_phone VARCHAR(20)) RETURNS VARCHAR(4) READS SQL DATA DETERMINISTIC BEGIN RETURN RIGHT(TRIM(p_phone), 4); END$$ DELIMITER ;
注意点:
DELIMITER $$是必需的,否则分号会被误认为语句结束
READS SQL DATA可省略(本例没查表),但若函数内含
SELECT ... FROM就必须声明
DETERMINISTIC表示相同输入总得相同输出;若含
NOW()、
RAND()等,必须改用
NOT DETERMINISTIC
调用自定义函数与常见陷阱
函数可直接用于
SELECT、
WHERE、
ORDER BY中,但不能用于存储过程体外的赋值语句(如
SET @x = myfunc(...)是合法的,但
SELECT myfunc(...) INTO @x更通用)。
典型误用:
在函数体内调用存储过程(不允许) 试图返回多列或多行(函数不支持,该用视图或存储过程) 参数名和表字段名冲突导致Unknown column错误(建议参数加前缀如
p_) 函数中使用未声明的变量(MySQL 函数不支持
DECLARE变量以外的自由变量)
查看、修改与删除函数
函数属于数据库对象,元数据存于
mysql.proc,但推荐用标准方式管理: 查看已创建函数:
SHOW FUNCTION STATUS WHERE Db = 'your_db';查看函数定义:
SHOW CREATE FUNCTION get_phone_tail;删除函数:
DROP FUNCTION IF EXISTS get_phone_tail;修改函数:没有
ALTER FUNCTION,必须先
DROP再
CREATE
函数体内的逻辑变更无法热更新,且函数被视图或其它函数引用时,
DROP会失败(报错
ERROR 1305),需先检查依赖。
