悠悠楠杉
SQL中使用NOW()函数获取当前日期时间的实用指南
在日常数据库操作中,获取系统当前日期时间是最基础却至关重要的功能。作为开发人员,我曾遇到过因时区设置错误导致订单时间全部偏差8小时的生产事故,这让我深刻认识到正确使用时间函数的重要性。
一、NOW()函数基础用法
在MySQL中,NOW()函数返回的是当前日期和时间,格式为'YYYY-MM-DD HH:MM:SS':
sql
SELECT NOW(); -- 输出: 2023-08-20 14:30:45
与SYSDATE()的区别在于:
- NOW()返回语句开始执行时的时间
- SYSDATE()返回函数调用时的时间
在事务中这个差异尤为明显:
sql
BEGIN;
SELECT NOW(), SYSDATE(); -- 两个值相同
WAITFOR DELAY '00:00:05';
SELECT NOW(), SYSDATE(); -- NOW()不变,SYSDATE()延迟5秒
COMMIT;
二、不同数据库的等效函数
SQL Server使用GETDATE():
sql SELECT GETDATE(); -- 2023-08-20 14:32:10.123
Oracle采用SYSDATE:
sql SELECT SYSDATE FROM DUAL; -- 20-AUG-23
PostgreSQL支持两种写法:
sql SELECT NOW(), CURRENT_TIMESTAMP; -- 2023-08-20 14:33:25.456+08
三、实际应用场景案例
记录创建时间(最经典用法)
sql CREATE TABLE orders ( id INT PRIMARY KEY, create_time DATETIME DEFAULT NOW() );
条件筛选当天数据
sql SELECT * FROM logs WHERE DATE(create_time) = CURDATE();
计算时间差(配合TIMESTAMPDIFF)
sql SELECT TIMESTAMPDIFF(MINUTE, start_time, NOW()) FROM meetings WHERE status = 'ongoing';
生成时间序列报告
sql SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:00') AS hour_start, COUNT(*) AS orders FROM orders GROUP BY hour_start;
定时任务条件判断
sql UPDATE promotions SET status = 'expired' WHERE end_time < NOW();
四、时区处理技巧
跨时区系统需要特别注意:sql
-- 设置会话时区
SET time_zone = '+08:00';
-- 转换为UTC时间
SELECT CONVERTTZ(NOW(), @@session.timezone, '+00:00');
五、性能优化建议
- 在大型表上避免使用函数计算:sql
-- 不推荐
SELECT * FROM bigtable WHERE DATE(createtime) = CURDATE();
-- 推荐写法
SELECT * FROM bigtable
WHERE createtime >= CURDATE()
AND createtime < DATEADD(CURDATE(), INTERVAL 1 DAY);
- 建立函数索引(MySQL 8.0+):
sql CREATE INDEX idx_date_created ON orders((DATE(create_time)));
六、日期格式化展示
根据不同地区需求调整显示格式:sql
-- 中文格式
SELECT DATEFORMAT(NOW(), '%Y年%m月%d日 %H时%i分') AS cntime;
-- ISO格式
SELECT DATEFORMAT(NOW(), '%Y-%m-%dT%TZ') AS isotime;
七、常见问题解决方案
问题1:为什么NOW()插入的值全部相同?
这是因为在批量插入时,MySQL会缓存NOW()值。如需不同时间戳,应在应用层生成值后插入。
问题2:如何获取毫秒级精度?
MySQL 5.6+可使用NOW(6):
sql
SELECT NOW(6); -- 2023-08-20 14:35:45.123456
问题3:如何仅获取日期或时间部分?
sql
SELECT DATE(NOW()), TIME(NOW()); -- 2023-08-20 | 14:36:02
八、高级应用:生成测试数据
sql
INSERT INTO user_login (user_id, login_time)
SELECT
id,
NOW() - INTERVAL FLOOR(RAND() * 30) DAY
FROM users;
掌握这些技巧后,您将能像经验丰富的DBA一样游刃有余地处理各类时间操作需求。记得在实际项目中根据具体数据库类型选择对应函数,并始终考虑时区因素的影响。