1. MySQL内置函数深度解析:从基础到实战
作为一名数据库开发工程师,我经常需要处理各种复杂的数据操作。MySQL内置函数就像瑞士军刀,能大幅提升我们的工作效率。今天我就结合多年实战经验,系统梳理最常用的日期、字符串和数学函数,并分享一些教科书上不会写的实用技巧。
2. 日期函数:时间处理的利器
2.1 基础时间获取函数
获取当前时间是数据库操作中最基础的需求。MySQL提供了多个函数,各有特点:
sql复制-- 获取当前日期(不包含时间)
SELECT CURRENT_DATE(); -- 输出:2023-08-15
-- 获取当前时间(不包含日期)
SELECT CURRENT_TIME(); -- 输出:14:30:45
-- 获取完整时间戳(最常用)
SELECT NOW(); -- 输出:2023-08-15 14:30:45
SELECT CURRENT_TIMESTAMP(); -- 与NOW()等效
实际开发中,NOW()是最常用的选择,因为它能同时获取日期和时间,适合大多数场景。在需要精确到微秒时,可以使用NOW(6)获取6位微秒数。
2.2 日期运算与转换
2.2.1 日期加减运算
处理订单有效期、会员到期日等场景时,日期加减是刚需:
sql复制-- 日期加10天(常用于计算到期日)
SELECT DATE_ADD('2023-08-15', INTERVAL 10 DAY); -- 输出:2023-08-25
-- 日期减1个月(会员有效期计算)
SELECT DATE_SUB('2023-08-15', INTERVAL 1 MONTH); -- 输出:2023-07-15
INTERVAL关键字支持多种单位:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND等,非常灵活。
2.2.2 日期差值计算
计算两个日期的间隔是天数差还是工作日差?DATEDIFF帮你解决:
sql复制-- 计算两个日期相差的天数
SELECT DATEDIFF('2023-08-20', '2023-08-15'); -- 输出:5
-- 计算年龄(精确到天)
SELECT DATEDIFF(NOW(), '1990-05-20')/365 AS age;
注意:DATEDIFF只计算日期部分差值,忽略时间部分。如果需要计算时间差,可以使用TIMESTAMPDIFF函数。
2.3 实战案例:留言板系统
让我们看一个真实的留言板系统案例:
sql复制-- 创建留言表
CREATE TABLE msg (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(200) NOT NULL,
sendtime DATETIME,
user_id INT
);
-- 插入测试数据
INSERT INTO msg(content, sendtime, user_id) VALUES
('产品什么时候发货?', NOW(), 1001),
('已收到货,质量不错', DATE_SUB(NOW(), INTERVAL 5 MINUTE), 1002),
('客服响应太慢了!', DATE_SUB(NOW(), INTERVAL 30 MINUTE), 1003);
-- 查询最近10分钟的留言(客服实时监控)
SELECT * FROM msg
WHERE sendtime > DATE_SUB(NOW(), INTERVAL 10 MINUTE);
-- 按日期统计留言量
SELECT DATE(sendtime) AS day, COUNT(*) AS count
FROM msg
GROUP BY DATE(sendtime);
这个案例展示了日期函数在实际业务中的应用场景,特别是DATE_SUB和DATE函数的使用技巧。
3. 字符串函数:文本处理专家
3.1 字符串基本操作
3.1.1 连接与截取
sql复制-- 字符串连接(用户全名拼接)
SELECT CONCAT(last_name, ' ', first_name) AS full_name
FROM users;
-- 截取子串(提取订单号前两位)
SELECT SUBSTRING(order_no, 1, 2) AS order_prefix
FROM orders;
性能提示:在数据量大的表中,避免在WHERE条件中使用SUBSTRING等函数,会导致索引失效。可以先创建计算列再建立索引。
3.1.2 大小写转换与空格处理
sql复制-- 统一用户名格式(首字母大写)
SELECT CONCAT(
UPPER(SUBSTRING(username, 1, 1)),
LOWER(SUBSTRING(username, 2))
) AS formatted_name FROM users;
-- 去除两端空格(用户输入清理)
UPDATE products SET name = TRIM(name);
3.2 高级字符串处理
3.2.1 字符串查找与替换
sql复制-- 查找子串位置(检查危险字符)
SELECT INSTR(comment, '<script>') AS xss_pos
FROM comments;
-- 安全替换(屏蔽敏感词)
UPDATE posts SET content = REPLACE(content, '敏感词', '***');
3.2.2 字符集与长度处理
sql复制-- 检测字符集(处理乱码问题)
SELECT CHARSET(title) FROM articles;
-- 计算字符串长度(注意字节与字符的区别)
SELECT
LENGTH('中文') AS byte_length, -- 返回6(UTF-8)
CHAR_LENGTH('中文') AS char_length; -- 返回2
重要区别:LENGTH计算字节数,CHAR_LENGTH计算字符数。处理多字节字符时一定要用CHAR_LENGTH。
4. 数学函数:数值计算能手
4.1 基础数学运算
sql复制-- 四舍五入(金额处理)
SELECT ROUND(123.4567, 2); -- 输出:123.46
-- 向上取整(分页计算)
SELECT CEIL(15/10) AS page_count; -- 输出:2
-- 随机数(抽奖功能)
SELECT * FROM users ORDER BY RAND() LIMIT 1;
4.2 数值格式化与比较
sql复制-- 格式化输出(财务报表)
SELECT FORMAT(1234567.89, 2); -- 输出:1,234,567.89
-- 数值比较(价格区间筛选)
SELECT product_name
FROM products
WHERE price BETWEEN 100 AND 200;
5. 其他实用函数
5.1 系统信息函数
sql复制-- 获取当前用户(审计日志)
SELECT USER(); -- 输出:root@localhost
-- 获取当前数据库
SELECT DATABASE();
5.2 加密函数
sql复制-- 密码加密存储(必须做!)
INSERT INTO users (username, password)
VALUES ('admin', MD5('s3cr3tP@ss'));
-- MySQL专用密码加密
SET PASSWORD = PASSWORD('new_password');
安全建议:MD5已经不够安全,建议使用SHA2或专门的密码哈希函数。生产环境绝对不要明文存储密码!
5.3 空值处理
sql复制-- 处理NULL值(报表展示)
SELECT
product_name,
IFNULL(stock, 0) AS stock,
IFNULL(price, 'N/A') AS price
FROM products;
6. 性能优化与常见问题
6.1 函数使用最佳实践
-
索引失效陷阱:WHERE条件中使用函数会导致索引失效
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函数
6.2 常见问题排查
-
时区问题:MySQL时区与系统时区不一致导致时间显示错误
sql复制-- 查看当前时区设置 SELECT @@global.time_zone, @@session.time_zone; -- 临时设置时区 SET time_zone = '+08:00'; -
字符集乱码:连接字符集与表字符集不一致
sql复制-- 查看字符集设置 SHOW VARIABLES LIKE 'character_set%'; -
隐式类型转换:字符串与数字比较时的意外行为
sql复制-- 可能产生意外结果 SELECT * FROM products WHERE product_id = '123abc';
7. 高级应用技巧
7.1 自定义函数
当内置函数不够用时,可以创建自定义函数:
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 employees;
7.2 函数组合使用
灵活组合函数解决复杂问题:
sql复制-- 生成随机用户名(测试数据准备)
SELECT CONCAT(
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ', FLOOR(1 + RAND() * 26), 1),
SUBSTRING('abcdefghijklmnopqrstuvwxyz', FLOOR(1 + RAND() * 26), 5),
FLOOR(RAND() * 100)
) AS random_username;
在实际项目中,我经常使用这些函数组合来处理数据清洗、报表生成等任务。掌握这些函数就像拥有了数据库操作的"快捷键",能极大提升开发效率。