SQL中VARCHAR类型存储的日期时间如何正确筛选?
解决VARCHAR类型日期时间的筛选问题
你的问题出在直接用字符串比较日期时间——VARCHAR类型的比较是按字符顺序逐个比对的,和实际的日期时间逻辑完全不符,这就是为什么你的查询没返回预期结果。比如字符串"01-12-2017,9:00"会被认为比"30-11-2017,7:30"小,但实际日期12月1日是晚于11月30日的,自然不会被筛选出来。
正确的做法是把存储的VARCHAR字符串转换成数据库原生的日期时间类型,再进行比较。下面针对主流数据库给出具体方案:
MySQL/MariaDB 方案
使用STR_TO_DATE()函数将字符串解析为DATETIME类型,格式符要和你的存储格式完全对应:
SELECT * FROM timetrack WHERE STR_TO_DATE(startDateAndTime, '%d-%m-%Y,%H:%i') >= STR_TO_DATE('30-11-2017,7:30', '%d-%m-%Y,%H:%i');
%d:两位数字的日期(01-31)%m:两位数字的月份(01-12)%Y:四位数字的年份%H:%i:24小时制的小时和分钟
PostgreSQL 方案
用TO_TIMESTAMP()函数转换,指定匹配的格式字符串:
SELECT * FROM timetrack WHERE TO_TIMESTAMP(startDateAndTime, 'DD-MM-YYYY,HH24:MI') >= TO_TIMESTAMP('30-11-2017,7:30', 'DD-MM-YYYY,HH24:MI');
SQL Server 方案
可以用PARSE()函数指定文化(英式日期格式对应en-GB),或者用CONVERT()配合字符串替换:
方法1:PARSE函数
SELECT * FROM timetrack WHERE PARSE(startDateAndTime AS DATETIME USING 'en-GB') >= PARSE('30-11-2017,7:30' AS DATETIME USING 'en-GB');
方法2:CONVERT函数
先把逗号替换成空格,再用格式代码105(对应dd-mm-yyyy)转换:
SELECT * FROM timetrack WHERE CONVERT(DATETIME, REPLACE(startDateAndTime, ',', ' '), 105) >= CONVERT(DATETIME, REPLACE('30-11-2017,7:30', ',', ' '), 105);
最佳实践
虽然上述转换可以解决当前问题,但长期来看强烈建议你把startDateAndTime字段的类型从VARCHAR改成DATETIME(或TIMESTAMP):
- 这样查询可以利用索引,大幅提升性能
- 避免存入格式错误的日期字符串(比如"31-02-2024"这种无效日期)
- 后续所有日期时间相关的操作(排序、计算、筛选)都会更简单可靠
内容的提问来源于stack exchange,提问作者Rana Umair
相关产品推荐
相关产品推荐

