引言
MySQL提供了丰富的内置函数来处理字符串和日期。掌握这些函数能大幅提升开发效率。
一、字符串函数
1.1 CONCAT() / CONCAT_WS() - 拼接
-- CONCAT:拼接字符串
SELECT CONCAT('Hello', ' ', 'World'); -- Hello World
-- CONCAT_WS:指定分隔符拼接
SELECT CONCAT_WS('-', '2024', '11', '21'); -- 2024-11-21
-- 实战:拼接姓名
SELECT CONCAT(last_name, first_name) AS full_name FROM users;
-- 处理NULL
SELECT CONCAT('Hello', NULL); -- NULL
SELECT CONCAT_WS(',', 'A', NULL, 'C'); -- A,C(忽略NULL)
1.2 SUBSTRING() / SUBSTR() - 截取
-- SUBSTRING(str, pos, len)
SELECT SUBSTRING('Hello World', 1, 5); -- Hello(从位置1开始,长度5)
SELECT SUBSTRING('Hello World', 7); -- World(从位置7到结尾)
SELECT SUBSTRING('Hello World', -5); -- World(从右边第5个)
-- 实战:提取手机号后4位
SELECT SUBSTRING(phone, -4) FROM users;
1.3 LENGTH() / CHAR_LENGTH() - 长度
-- LENGTH:字节长度
SELECT LENGTH('Hello'); -- 5
SELECT LENGTH('你好'); -- 6(UTF-8,每个汉字3字节)
-- CHAR_LENGTH:字符长度
SELECT CHAR_LENGTH('Hello'); -- 5
SELECT CHAR_LENGTH('你好'); -- 2
-- 实战:过滤长度
SELECT * FROM products WHERE CHAR_LENGTH(name) > 10;
1.4 UPPER() / LOWER() - 大小写
SELECT UPPER('hello'); -- HELLO
SELECT LOWER('WORLD'); -- world
-- 实战:不区分大小写查询
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
1.5 TRIM() / LTRIM() / RTRIM() - 去空格
SELECT TRIM(' Hello '); -- 'Hello'
SELECT LTRIM(' Hello '); -- 'Hello '
SELECT RTRIM(' Hello '); -- ' Hello'
SELECT TRIM('x' FROM 'xxxHelloxxx'); -- 'Hello'
1.6 REPLACE() - 替换
SELECT REPLACE('Hello World', 'World', 'MySQL'); -- Hello MySQL
-- 实战:隐藏手机号中间4位
SELECT CONCAT(
SUBSTRING(phone, 1, 3),
'****',
SUBSTRING(phone, -4)
) AS masked_phone
FROM users;
1.7 INSTR() / LOCATE() - 查找位置
SELECT INSTR('Hello World', 'World'); -- 7
SELECT LOCATE('o', 'Hello World'); -- 5
SELECT LOCATE('o', 'Hello World', 6); -- 8(从第6个位置开始找)
1.8 LEFT() / RIGHT() - 左右截取
SELECT LEFT('Hello World', 5); -- Hello
SELECT RIGHT('Hello World', 5); -- World
二、日期时间函数
2.1 NOW() / CURDATE() / CURTIME()
SELECT NOW(); -- 2024-11-21 19:00:00(当前日期时间)
SELECT CURDATE(); -- 2024-11-21(当前日期)
SELECT CURTIME(); -- 19:00:00(当前时间)
SELECT SYSDATE(); -- 2024-11-21 19:00:00(系统时间)
2.2 DATE_FORMAT() - 格式化
-- DATE_FORMAT(date, format)
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- 2024-11-21
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); -- 2024年11月21日
SELECT DATE_FORMAT(NOW(), '%H:%i:%s'); -- 19:00:00
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 2024-11-21 19:00:00
SELECT DATE_FORMAT(NOW(), '%W, %M %d, %Y'); -- Thursday, November 21, 2024
常用格式符:
%Y:4位年份%m:2位月份%d:2位日期%H:24小时制%i:分钟%s:秒%W:星期名%M:月份名
2.3 STR_TO_DATE() - 字符串转日期
SELECT STR_TO_DATE('2024-11-21', '%Y-%m-%d'); -- 2024-11-21
SELECT STR_TO_DATE('21/11/2024', '%d/%m/%Y'); -- 2024-11-21
SELECT STR_TO_DATE('2024年11月21日', '%Y年%m月%d日'); -- 2024-11-21
2.4 DATE_ADD() / DATE_SUB() - 日期加减
-- DATE_ADD(date, INTERVAL expr unit)
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY); -- 明天
SELECT DATE_ADD(NOW(), INTERVAL 1 MONTH); -- 下个月
SELECT DATE_ADD(NOW(), INTERVAL 1 YEAR); -- 明年
SELECT DATE_ADD(NOW(), INTERVAL -7 DAY); -- 7天前
-- DATE_SUB
SELECT DATE_SUB(NOW(), INTERVAL 1 WEEK); -- 1周前
SELECT DATE_SUB(NOW(), INTERVAL 30 DAY); -- 30天前
-- 实战:查询最近7天的订单
SELECT * FROM orders
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);
2.5 DATEDIFF() - 日期差
-- DATEDIFF(date1, date2):返回天数差
SELECT DATEDIFF('2024-11-21', '2024-11-01'); -- 20
SELECT DATEDIFF(NOW(), '2024-01-01'); -- 距离今年1月1日的天数
-- 实战:计算会员天数
SELECT name,
DATEDIFF(NOW(), register_date) AS member_days
FROM users;
2.6 TIMESTAMPDIFF() - 更精确的时间差
-- TIMESTAMPDIFF(unit, datetime1, datetime2)
SELECT TIMESTAMPDIFF(SECOND, '2024-11-21 10:00:00', '2024-11-21 11:00:00'); -- 3600
SELECT TIMESTAMPDIFF(MINUTE, '2024-11-21 10:00:00', '2024-11-21 11:00:00'); -- 60
SELECT TIMESTAMPDIFF(HOUR, '2024-11-21 10:00:00', '2024-11-21 11:00:00'); -- 1
SELECT TIMESTAMPDIFF(DAY, '2024-11-01', '2024-11-21'); -- 20
SELECT TIMESTAMPDIFF(MONTH, '2024-01-01', '2024-11-21'); -- 10
SELECT TIMESTAMPDIFF(YEAR, '2020-01-01', '2024-11-21'); -- 4
2.7 EXTRACT() - 提取日期部分
SELECT EXTRACT(YEAR FROM NOW()); -- 2024
SELECT EXTRACT(MONTH FROM NOW()); -- 11
SELECT EXTRACT(DAY FROM NOW()); -- 21
SELECT EXTRACT(HOUR FROM NOW()); -- 19
-- 或使用专用函数
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
2.8 DAYOFWEEK() / WEEKDAY() - 星期
SELECT DAYOFWEEK(NOW()); -- 1-7(周日=1)
SELECT WEEKDAY(NOW()); -- 0-6(周一=0)
SELECT DAYNAME(NOW()); -- Thursday
2.9 LAST_DAY() - 月末
SELECT LAST_DAY('2024-11-21'); -- 2024-11-30
SELECT LAST_DAY(NOW()); -- 本月最后一天
三、实战案例
案例1:生成订单编号
SELECT CONCAT(
'ORD',
DATE_FORMAT(NOW(), '%Y%m%d'),
LPAD(id, 6, '0')
) AS order_no
FROM orders;
-- 结果:ORD20241121000001
案例2:按月统计
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month,
COUNT(*) AS order_count,
SUM(amount) AS total_amount
FROM orders
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 12 MONTH)
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
ORDER BY month;
案例3:计算年龄
SELECT name,
birthday,
TIMESTAMPDIFF(YEAR, birthday, NOW()) AS age
FROM users;
案例4:格式化显示
-- 显示"3天前"、"1小时前"
SELECT
CASE
WHEN TIMESTAMPDIFF(MINUTE, created_at, NOW()) < 60
THEN CONCAT(TIMESTAMPDIFF(MINUTE, created_at, NOW()), '分钟前')
WHEN TIMESTAMPDIFF(HOUR, created_at, NOW()) < 24
THEN CONCAT(TIMESTAMPDIFF(HOUR, created_at, NOW()), '小时前')
WHEN TIMESTAMPDIFF(DAY, created_at, NOW()) < 30
THEN CONCAT(TIMESTAMPDIFF(DAY, created_at, NOW()), '天前')
ELSE DATE_FORMAT(created_at, '%Y-%m-%d')
END AS time_display
FROM articles;
四、总结
常用函数速查
字符串:
- 拼接:CONCAT、CONCAT_WS
- 截取:SUBSTRING、LEFT、RIGHT
- 长度:LENGTH、CHAR_LENGTH
- 大小写:UPPER、LOWER
- 处理:TRIM、REPLACE
日期时间:
- 获取:NOW、CURDATE、CURTIME
- 格式化:DATE_FORMAT、STR_TO_DATE
- 计算:DATE_ADD、DATE_SUB、DATEDIFF
- 提取:YEAR、MONTH、DAY、EXTRACT
记忆口诀
字符串函数多又全,CONCAT拼接SUBSTRING截,
UPPER大写LOWER小,TRIM去空REPLACE换。
日期函数也常用,NOW当前FORMAT格式,
ADD增加SUB减少,DATEDIFF计算天数差。
本文字数:约3,200字 难度等级:⭐⭐(SQL进阶)