MySQL函数是接收输入、执行逻辑并返回确定值的计算单元,不修改数据,用于SQL表达式中即时计算或转换;需区分单行函数(如UPPER)与聚合函数(如COUNT),二者语义和用法截然不同。

MySQL函数是数据库内置或用户编写的“计算单元”,它接收输入、执行逻辑、返回一个确定值,且不修改原始数据。 它不是存储过程,不能执行INSERT/UPDATE等语句;也不是触发器,不响应事件。它的核心用途就一个:在SQL表达式里做即时计算或转换——比如把日期格式化、把字符串拼接、把数字四舍五入,而且能用在SELECT、WHERE、ORDER BY任何位置。
为什么必须分清“单行函数”和“聚合函数”
这是理解MySQL函数行为的底层分水岭:
-
COUNT()、AVG()、MAX()这类聚合函数作用于多行,返回单个统计结果;它们必须配合GROUP BY使用(或全表聚合),单独出现在SELECT中会隐式将整张表视为一组 -
UPPER()、SUBSTRING()、ROUND()这类单行函数对每一行独立运算,输入一行、输出一行,可直接和字段并列写在SELECT里,例如SELECT name, UPPER(name) FROM user - 混用时容易报错:比如在没
GROUP BY的查询里同时写name和COUNT(*),MySQL 5.7+默认会拒绝(严格模式下),因为语义冲突
CONCAT、IFNULL、CASE WHEN 这三类函数常被误当“万能胶”用
它们解决的是不同层面的问题,强行替代反而埋坑:
-
CONCAT()遇到NULL直接返回NULL,不是跳过——想安全拼接得先IFNULL(col, '')兜底,否则整条记录显示为空 -
IFNULL(a,b)只能处理两值判断,而CASE WHEN支持多分支和布尔表达式,比如CASE WHEN score >= 90 THEN 'A' WHEN score >= 80 THEN 'B' ELSE 'C' END,硬用嵌套IFNULL会极难读 -
CASE WHEN在WHERE中慎用:它本身不走索引,若写成WHERE CASE WHEN status=1 THEN id ELSE 0 END > 100,可能让本可用的id索引失效
自定义函数(UDF)不是“高级功能”,而是“生产红线”
很多团队在测试环境随手写CREATE FUNCTION,上线后才发现问题:
- MySQL默认禁用自定义函数创建(
log_bin_trust_function_creators=OFF),开启需DBA授权,且涉及主从复制安全策略 - 函数体里不能含
SELECT查表、不能改数据、不能调用非确定性函数(如RAND()、NOW()),否则声明DETERMINISTIC会失败 - 性能隐患:一个UDF被调用10万次,等于执行10万次函数体逻辑——比写在应用层循环更慢,尤其含复杂字符串处理时
- 真正该用UDF的场景极少:比如统一加密规则(
AES_ENCRYPT已内置)、特殊单位换算(如经纬度距离公式),而非替代WHERE条件或JOIN逻辑
函数不是语法糖,是数据库执行计划的一部分。写DATE_FORMAT(create_time, '%Y-%m')看似简单,但若create_time字段有索引,这个函数会让索引完全失效——这时候宁可用范围查询create_time BETWEEN '2025-01-01' AND '2025-01-31'。细节不在文档里,在explain出来的type和key字段中。










