1. MySQL内置函数概述
MySQL作为最流行的开源关系型数据库之一,其内置函数库是数据处理的核心武器库。这些预定义的函数可以直接在SQL语句中调用,无需额外编码就能实现复杂的数据转换、计算和格式化操作。根据我的项目经验,合理使用内置函数能减少约60%的应用程序代码量,同时显著提升查询性能。
内置函数主要分为六大类:
- 字符串函数:处理文本数据的利器
- 数值函数:数学运算和舍入控制
- 日期时间函数:时间维度数据处理
- 流程控制函数:实现SQL逻辑分支
- 聚合函数:GROUP BY的黄金搭档
- 系统信息函数:获取数据库元数据
重要提示:MySQL 8.0新增了窗口函数,这是分析型查询的革命性改进,我们会在第4章专门讲解。
2. 字符串处理函数实战精要
2.1 基础字符串操作
CONCAT() 是最常用的字符串拼接函数,但有个坑需要注意:
-- 当任何参数为NULL时,结果必为NULL SELECT CONCAT('Hello', NULL, 'World'); -- 返回NULL安全写法是使用CONCAT_WS()(带分隔符的拼接):
SELECT CONCAT_WS('-', '2023', NULL, '07'); -- 返回"2023-07"SUBSTRING() 的三种参数形式:
SELECT SUBSTRING('MySQL', 2), -- 从第2字符开始:"ySQL" SUBSTRING('MySQL', 2, 2), -- 从第2字符取2位:"yS" SUBSTRING('MySQL', -3); -- 倒数第3字符开始:"SQL"2.2 高级字符串处理
正则表达式函数是数据清洗的核武器:
-- 提取手机号中的数字 SELECT REGEXP_REPLACE('电话:138-1234-5678', '[^0-9]', ''); -- 返回"13812345678"JSON处理函数在API开发中特别实用:
SELECT JSON_EXTRACT('{"user": {"name": "Alice"}}', '$.user.name'), JSON_CONTAINS('["apple","orange"]', '"orange"');3. 数值与日期函数深度解析
3.1 数值计算陷阱规避
ROUND()的银行家舍入规则(四舍六入五成双):
SELECT ROUND(23.5), -- 24 ROUND(24.5); -- 24(不是25!)精确计算必须用DECIMAL类型:
-- 浮点数计算误差示例 SELECT 0.1 + 0.2; -- 返回0.30000000000000004 -- 正确做法 SELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2));3.2 日期时间处理秘籍
时区转换是跨国系统的必修课:
SELECT CONVERT_TZ('2023-07-20 12:00:00', '+00:00', '+08:00'), TIMESTAMPDIFF(HOUR, '2023-01-01', '2023-01-02');工作日计算方案:
-- 计算两个日期之间的工作日(排除周末) SELECT COUNT(*) - COUNT(CASE WHEN WEEKDAY(date_field) IN (5,6) THEN 1 END) FROM date_table WHERE date_field BETWEEN start_date AND end_date;4. 窗口函数与高级分析
4.1 窗口函数核心用法
排名函数的区别:
SELECT name, score, ROW_NUMBER() OVER(ORDER BY score DESC) AS '行号', RANK() OVER(ORDER BY score DESC) AS '排名', DENSE_RANK() OVER(ORDER BY score DESC) AS '密集排名' FROM students;移动平均计算:
SELECT date, sales, AVG(sales) OVER(ORDER BY date ROWS 2 PRECEDING) AS '3日移动平均' FROM sales_data;4.2 性能优化要点
窗口函数可能导致临时表创建,在大数据量时需要注意:
-- 低效写法(全表排序) SELECT *, ROW_NUMBER() OVER(ORDER BY id) FROM large_table; -- 优化方案(使用索引列排序) SELECT *, ROW_NUMBER() OVER(ORDER BY indexed_column) FROM large_table;5. 函数性能优化与避坑指南
5.1 索引失效场景
这些函数会导致索引失效:
-- 索引列使用函数 SELECT * FROM users WHERE YEAR(create_time) = 2023; -- 优化方案 SELECT * FROM users WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';5.2 存储过程函数缓存
频繁调用的复杂函数建议封装为存储过程:
DELIMITER // CREATE FUNCTION calc_bonus(salary DECIMAL(10,2), years INT) RETURNS DECIMAL(10,2) DETERMINISTIC BEGIN DECLARE bonus DECIMAL(10,2); -- 复杂计算逻辑 RETURN bonus; END // DELIMITER ;6. 版本差异与兼容方案
6.1 MySQL 5.7 vs 8.0函数差异
JSON处理函数对比:
-- MySQL 5.7 SELECT JSON_EXTRACT('{"name":"John"}', '$.name'); -- MySQL 8.0简写 SELECT '{"name":"John"}'-'$.name';6.2 跨数据库兼容方案
日期格式化差异处理:
-- MySQL SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- PostgreSQL兼容写法 CREATE FUNCTION pg_to_date(d TIMESTAMP) RETURNS VARCHAR(10) DETERMINISTIC BEGIN RETURN DATE_FORMAT(d, '%Y-%m-%d'); END;在实际项目中,我总结出三个黄金原则:
- 简单运算优先用SQL函数,复杂逻辑交给应用程序
- 批量处理数据时,尽量用一条SQL完成多个函数调用
- 关键业务函数必须编写单元测试用例