MySQL内置函数是数据库系统中预定义的一系列功能模块,它们可以直接在SQL语句中调用,无需额外安装或配置。这些函数就像是数据库工具箱里的各种工具,能帮我们高效地处理数据转换、计算、格式化等常见操作。
我在实际项目中最常用的几类函数包括:
这些函数在数据清洗、报表生成、业务逻辑实现等场景中发挥着关键作用。比如上周我就用DATE_FORMAT函数快速解决了客户要求的特殊日期格式显示问题,原本需要应用程序处理的逻辑,直接在SQL层面就搞定了。
CONCAT函数是我使用频率最高的字符串函数之一,它能把多个字符串拼接在一起:
sql复制SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM employees;
注意:CONCAT遇到NULL参数会返回NULL,可以用CONCAT_WS(带分隔符的版本)或IFNULL处理
SUBSTRING函数用于截取字符串,参数配置很灵活:
sql复制-- 从第2个字符开始截取3个字符
SELECT SUBSTRING('MySQL', 2, 3); -- 结果'ySQ'
-- 负数位置表示从末尾倒数
SELECT SUBSTRING('Database', -4, 4); -- 结果'base'
LOCATE函数找子串位置时特别实用:
sql复制-- 返回子串首次出现位置(从1开始计数)
SELECT LOCATE('SQL', 'MySQL SQL'); -- 结果3
REPLACE函数做批量替换时效率很高:
sql复制UPDATE articles
SET content = REPLACE(content, '旧产品', '新产品')
WHERE publish_date > '2023-01-01';
实战经验:大数据量替换时,建议先用SELECT测试影响范围,避免误操作
ROUND函数的银行家舍入规则需要注意:
sql复制SELECT
ROUND(12.5), -- 12 (向最近的偶数舍入)
ROUND(13.5); -- 14
RAND函数生成随机数的小技巧:
sql复制-- 获取10-20之间的随机整数
SELECT FLOOR(10 + RAND() * 11);
处理财务数据时,FORMAT函数很实用:
sql复制SELECT FORMAT(1234567.891, 2); -- 输出'1,234,567.89'
MOD函数判断奇偶性的经典用法:
sql复制SELECT id FROM users WHERE MOD(id, 2) = 0; -- 获取偶数ID
DATEDIFF计算日期差值的坑:
sql复制-- 计算两个日期相差天数
SELECT DATEDIFF('2023-12-31', '2023-01-01'); -- 364天
-- 注意:时间部分会被忽略
SELECT DATEDIFF('2023-01-01 23:59:59', '2023-01-02 00:00:01'); -- -1天
DATE_ADD处理月末日期时的智能表现:
sql复制-- 自动处理2月月末
SELECT DATE_ADD('2023-01-31', INTERVAL 1 MONTH); -- '2023-02-28'
DATE_FORMAT的格式字符串示例:
sql复制SELECT
DATE_FORMAT(NOW(), '%Y年%m月%d日 %H时%i分') AS cn_time,
DATE_FORMAT(NOW(), '%W, %M %e %Y') AS en_time;
性能提示:在WHERE条件中对日期列使用函数会导致索引失效,应尽量转换为对裸列的条件判断
GROUP_CONCAT的实用配置:
sql复制SELECT
department_id,
GROUP_CONCAT(
DISTINCT employee_name
ORDER BY hire_date
SEPARATOR '|'
) AS team_members
FROM employees
GROUP BY department_id;
COUNT的三个用法区别:
sql复制SELECT
COUNT(*), -- 统计行数
COUNT(1), -- 同上,但语义更明确
COUNT(salary) -- 统计非NULL值
FROM employees;
RANK vs DENSE_RANK的实际差异:
sql复制SELECT
product_name,
sales,
RANK() OVER (ORDER BY sales DESC) AS rank,
DENSE_RANK() OVER (ORDER BY sales DESC) AS dense_rank
FROM products;
实现多条件分支的两种写法:
sql复制-- 简单CASE
SELECT
CASE department_id
WHEN 1 THEN '研发部'
WHEN 2 THEN '市场部'
ELSE '其他部门'
END AS dept_name
FROM employees;
-- 搜索CASE(更灵活)
SELECT
CASE
WHEN salary > 10000 THEN '高薪'
WHEN salary > 5000 THEN '中等'
ELSE '基础'
END AS salary_level
FROM employees;
处理NULL值的优雅方式:
sql复制SELECT
product_name,
IF(stock IS NULL, 0, stock) AS actual_stock
FROM products;
最典型的索引失效场景:
sql复制-- 索引失效写法
SELECT * FROM orders WHERE YEAR(order_date) = 2023;
-- 优化写法(允许使用索引)
SELECT * FROM orders
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';
字符串函数的性能对比测试:
sql复制-- 测试10万次运算耗时
SELECT BENCHMARK(100000,
CONCAT(SUBSTRING('performance_test', 5, 5), '123')
); -- 平均0.05秒
SELECT BENCHMARK(100000,
SUBSTRING('performance_test', 5, 5) || '123'
); -- 平均0.03秒(某些版本更快)
虽然内置函数很强大,但遇到特殊业务逻辑时,可以创建存储函数来扩展:
sql复制DELIMITER //
CREATE FUNCTION get_age(birth_date DATE)
RETURNS INT
DETERMINISTIC
BEGIN
RETURN TIMESTAMPDIFF(YEAR, birth_date, CURDATE());
END //
DELIMITER ;
-- 使用示例
SELECT name, get_age(birthday) AS age FROM users;
开发建议:自定义函数命名建议加前缀区分,如'fn_'或'公司缩写_',避免与未来MySQL新增内置函数冲突
MySQL 8.0新增的函数特性:
函数行为变更示例:
sql复制-- MySQL 5.7: GROUP_CONCAT默认长度限制1024
-- MySQL 8.0: 默认长度增加到1MB
SET SESSION group_concat_max_len = 1000000; -- 可调整
使用SELECT直接测试函数:
sql复制-- 测试字符串函数
SELECT
original_value,
FUNCTION_APPLIED(original_value) AS result
FROM (SELECT 'test string' AS original_value) tmp;
日期格式错误的处理:
sql复制-- 错误写法(依赖系统日期格式设置)
SELECT STR_TO_DATE('01/02/2023', '%d/%m/%Y');
-- 安全写法(明确格式)
SELECT STR_TO_DATE('2023-02-01', '%Y-%m-%d');
隐式类型转换问题:
sql复制-- 可能产生意外结果
SELECT '10' + '20'; -- 30(数值相加)
SELECT CONCAT('10', '20'); -- '1020'(字符串连接)
在实际项目中,我总结出一条黄金法则:对任何不确定的函数行为,先用小数据集测试验证,特别是涉及数据修改的操作。曾经有一次我误用了REPLACE函数,因为没有限制WHERE条件,导致整表数据被意外更新,这个教训让我至今记忆犹新。