1. MySQL函数基础与使用场景
MySQL作为最流行的关系型数据库之一,其内置函数体系是数据处理的核心工具。这些函数主要分为三大类:字符串处理、日期时间计算和数学运算,每类函数在真实业务场景中都扮演着关键角色。
字符串函数在用户数据清洗、日志解析等场景不可或缺。比如用户注册时输入的不规范姓名,可以用CONCAT()拼接、SUBSTRING()截取或TRIM()去除空格;产品SKU编码的解析则常用LOCATE()和REPLACE()。
日期函数在报表统计、时效计算中应用广泛。电商平台需要DATE_ADD()计算促销截止时间,DATEDIFF()分析用户复购周期;金融系统依赖LAST_DAY()生成月结报表,UNIX_TIMESTAMP()记录精确到秒的操作时间戳。
数学函数支撑着数据分析与业务逻辑。ROUND()处理金融金额精度,RAND()生成抽奖随机数,LOG()计算增长率指标。在机器学习特征工程中,这些函数常直接用于SQL层面的特征计算。
提示:MySQL 8.0新增了窗口函数和JSON处理函数,但本文聚焦最通用的基础函数,这些函数在所有MySQL版本中保持兼容。
函数调用的基础语法遵循函数名(参数1, 参数2...)的格式。特殊情况下:
- 无参数函数直接写函数名,如NOW()
- 参数可以是字段名、常量或表达式
- 多数函数支持嵌套调用,如CONCAT(SUBSTRING(name,1,1),'***')
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 字符串处理函数详解
2.1 基础字符串操作
LENGTH()和CHAR_LENGTH()都能获取字符串长度,但处理多字节字符时差异显著:
sql复制SELECT
LENGTH('中国') AS byte_length, -- 返回6(UTF-8编码)
CHAR_LENGTH('中国') AS char_length; -- 返回2
CONCAT()的隐式类型转换可能带来意外结果:
sql复制-- 当连接数字和字符串时
SELECT CONCAT(123, 'abc'); -- '123abc'
SELECT CONCAT('订单:', NULL); -- 返回NULL
注意:CONCAT_WS()是更安全的选择,它忽略NULL值并自动添加分隔符:
sql复制SELECT CONCAT_WS('-', '2020', NULL, '01'); -- '2020-01'
2.2 字符串截取与定位
SUBSTRING()的三种参数形式:
sql复制SUBSTRING('MySQL', 2, 3), -- 'ySQ' (从第2字符取3个)
SUBSTRING('MySQL', 2), -- 'ySQL' (从第2字符到结尾)
SUBSTRING('MySQL', -3, 2) -- 'SQ' (倒数第3字符取2个)
LOCATE()与INSTR()的对比:
sql复制SELECT
LOCATE('ql', 'MySQL'), -- 4 (返回首次出现位置)
INSTR('MySQL', 'ql'), -- 4 (功能相同)
LOCATE('QL', 'MySQL'); -- 0 (大小写敏感)
2.3 字符串替换与格式化
REPLACE()的实际应用场景:
sql复制-- 手机号脱敏处理
SELECT REPLACE('13800138000', '13800', '*****'); -- '*****138000'
-- 批量更新示例
UPDATE users SET address = REPLACE(address, '街道', '街');
FORMAT()的金融数值处理:
sql复制SELECT
FORMAT(1234567.891, 2), -- '1,234,567.89'
FORMAT(1234567.891, 0); -- '1,234,568'
2.4 字符串拆分与组合
SPLIT_STR自定义函数实现(MySQL原生不支持SPLIT函数):
sql复制DELIMITER //
CREATE FUNCTION SPLIT_STR(str VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
BEGIN
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
delim, '');
END//
DELIMITER ;
-- 使用示例
SELECT SPLIT_STR('apple,orange,banana', ',', 2); -- 'orange'
3. 日期时间函数实战
3.1 基础日期获取与计算
日期获取函数的典型应用:
sql复制-- 获取当前日期时间
SELECT NOW(), -- '2023-08-20 14:30:45'
CURDATE(), -- '2023-08-20'
CURTIME(); -- '14:30:45'
-- 获取日期部分
SELECT DATE(NOW()), -- '2023-08-20'
TIME(NOW()); -- '14:30:45'
日期加减的三种方式:
sql复制-- 标准加减
SELECT DATE_ADD('2023-01-31', INTERVAL 1 MONTH), -- '2023-02-28'
DATE_SUB('2023-03-31', INTERVAL 1 MONTH); -- '2023-02-28'
-- 简写形式
SELECT '2023-01-31' + INTERVAL 1 MONTH,
'2023-03-31' - INTERVAL 1 MONTH;
-- 天数加减特例
SELECT ADDDATE('2023-01-31', 5), -- '2023-02-05'
SUBDATE('2023-01-31', 5); -- '2023-01-26'
3.2 日期格式化与解析
DATE_FORMAT()的格式化符号:
sql复制SELECT
DATE_FORMAT(NOW(), '%Y年%m月%d日 %H时%i分%s秒'), -- '2023年08月20日 14时30分45秒'
DATE_FORMAT(NOW(), '%W, %M %e, %Y'), -- 'Sunday, August 20, 2023'
DATE_FORMAT(NOW(), '%b %D %y %h:%i %p'); -- 'Aug 20th 23 02:30 PM'
STR_TO_DATE()的字符串解析:
sql复制SELECT
STR_TO_DATE('08/20/2023', '%m/%d/%Y'), -- '2023-08-20'
STR_TO_DATE('20-Aug-2023', '%d-%b-%Y'), -- '2023-08-20'
STR_TO_DATE('2023年08月20日', '%Y年%m月%d日'); -- '2023-08-20'
3.3 日期差异与提取
DATEDIFF()与TIMESTAMPDIFF()的对比:
sql复制SELECT
DATEDIFF('2023-08-25', '2023-08-20'), -- 5 (天数差)
TIMESTAMPDIFF(MINUTE, '2023-08-20 14:00', '2023-08-20 15:30'); -- 90 (分钟差)
日期部分提取的高效方案:
sql复制-- 传统方式
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
-- EXTRACT更灵活
SELECT
EXTRACT(YEAR FROM NOW()),
EXTRACT(YEAR_MONTH FROM NOW()), -- 202308
EXTRACT(DAY_HOUR FROM NOW()); -- 2014 (20日14时)
4. 数学运算函数解析
4.1 基础计算函数
ROUND()的银行家舍入规则:
sql复制SELECT
ROUND(2.5), -- 2 (向最近的偶数舍入)
ROUND(3.5), -- 4
ROUND(2.15, 1), -- 2.2
ROUND(2.25, 1); -- 2.2
CEIL()与FLOOR()的边界情况:
sql复制SELECT
CEIL(2.3), -- 3
CEIL(-2.3), -- -2
FLOOR(2.7), -- 2
FLOOR(-2.7); -- -3
4.2 高级数学运算
对数函数的计算精度:
sql复制SELECT
LOG(2, 8), -- 3.000000
LOG10(100), -- 2.000000
LN(EXP(2)); -- 2.000000
RAND()的应用技巧:
sql复制-- 随机排序
SELECT * FROM products ORDER BY RAND() LIMIT 5;
-- 生成区间随机数
SELECT FLOOR(10 + RAND() * 90); -- 10-99的随机整数
4.3 数值处理与进制转换
MOD()的负数处理:
sql复制SELECT
MOD(10, 3), -- 1
MOD(-10, 3), -- -1
MOD(10, -3), -- 1
MOD(-10, -3); -- -1
进制转换函数组:
sql复制SELECT
BIN(10), -- '1010'
OCT(10), -- '12'
HEX(255), -- 'FF'
CONV('A',16,10); -- '10'
5. 函数组合应用案例
5.1 用户数据脱敏处理
完整的用户信息脱敏方案:
sql复制SELECT
CONCAT(
LEFT(real_name, 1),
REPEAT('*', GREATEST(CHAR_LENGTH(real_name)-1, 0))
) AS name_mask,
CONCAT(
LEFT(mobile, 3),
'****',
RIGHT(mobile, 4)
) AS mobile_mask,
CONCAT(
YEAR(birthday),
'-**-**'
) AS birthday_mask
FROM users;
5.2 订单流水号生成
基于规则的订单号生成:
sql复制UPDATE orders
SET order_no = CONCAT(
DATE_FORMAT(NOW(), '%Y%m%d'),
LPAD(FLOOR(RAND()*10000), 4, '0')
)
WHERE order_no IS NULL;
5.3 促销活动时间计算
复杂促销规则实现:
sql复制SELECT
DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i') AS current_time,
DATE_FORMAT(DATE_ADD(
CURDATE(),
INTERVAL IF(HOUR(NOW())<12, 12, 36) HOUR
), '%Y-%m-%d %H:00') AS next_promotion_time,
TIMESTAMPDIFF(
MINUTE,
NOW(),
DATE_ADD(
LAST_DAY(NOW()),
INTERVAL 1 DAY
)
) AS minutes_until_month_end;
5.4 数据清洗转换
脏数据清洗方案:
sql复制UPDATE raw_data SET
product_code = UPPER(TRIM(product_code)),
weight_value = ROUND(IF(
weight_unit = 'lb',
weight_value * 0.453592,
weight_value
), 2),
weight_unit = 'kg',
expire_date = STR_TO_DATE(
REGEXP_REPLACE(expire_date, '[^0-9-]', ''),
'%Y-%m-%d'
)
WHERE data_status = 0;
6. 性能优化与避坑指南
6.1 函数使用性能陷阱
索引失效的典型场景:
sql复制-- 反面案例:索引失效
SELECT * FROM orders WHERE DATE_FORMAT(create_time,'%Y-%m')='2023-08';
-- 优化方案:使用范围查询
SELECT * FROM orders
WHERE create_time >= '2023-08-01'
AND create_time < '2023-09-01';
隐式类型转换问题:
sql复制-- 反面案例:全表扫描
SELECT * FROM products WHERE product_code = 12345;
-- 优化方案:类型一致
SELECT * FROM products WHERE product_code = '12345';
6.2 时区处理最佳实践
时区转换的推荐方案:
sql复制-- 存储统一使用UTC时间
INSERT INTO events(event_time) VALUES (UTC_TIMESTAMP());
-- 查询时按需转换
SELECT
event_time AS utc_time,
CONVERT_TZ(event_time, '+00:00', '+08:00') AS local_time
FROM events;
6.3 函数嵌套深度控制
过度嵌套的优化方案:
sql复制-- 反面案例:7层嵌套
SELECT CONCAT(
LEFT(
REPLACE(
SUBSTRING_INDEX(
REVERSE(
LPAD(
CONVERT(
ROUND(price*1.1, 2),
CHAR
),
10, '0'
)
),
'-', 1),
'0', ' '),
3),
' USD') FROM products;
-- 优化方案:分步处理
UPDATE products SET
temp_price = ROUND(price*1.1, 2),
temp_str = LPAD(CONVERT(temp_price, CHAR), 10, '0'),
temp_reversed = REVERSE(temp_str),
/* 其他步骤 */
display_price = final_result;
6.4 版本兼容性处理
5.7与8.0的函数差异:
sql复制-- JSON处理函数(8.0+)
SELECT JSON_EXTRACT('{"name":"John"}', '$.name');
-- 窗口函数(8.0+)
SELECT
name,
salary,
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank
FROM employees;
重要提示:生产环境使用新函数前,务必在测试库验证函数效果,特别是涉及数据修改的操作。对于关键业务逻辑,建议在应用层实现复杂计算,而非完全依赖数据库函数。
