在MySQL开发中,var并不是一个官方数据类型,它通常指VARCHAR字段或用户定义变量@var。当这些变量中存储的是日期字符串时,需要将其转换为DATE类型才能进行日期运算、范围查询和按天分组。直接对字符串使用日期函数往往会得到不可预期的结果,因为MySQL会尝试隐式转换,但隐式转换的规则依赖会话的日期格式设置,而且可能导致索引失效。因此,明确掌握VAR到DATE的转换方法非常重要。

一、先弄清VAR在MySQL中的实际含义
在MySQL中,var这个词通常有两种解释。第一种是VARCHAR数据类型的简写,比如定义一个字段为varchar(50),用来保存日期字符串。第二种是用户定义变量,也就是以@开头的变量,例如SET @var = '2023-05-12'。这两种var都不是真正的日期类型,它们只是字符串或变量容器。
DATE类型在MySQL内部以YYYY-MM-DD的格式存储,占用3个字节,支持从1000-01-01到9999-12-31的日期范围。DATE类型可以直接参与日期函数计算、日期比较和范围索引优化。而VARCHAR中存储的日期字符串可能包含不同的分隔符,比如2023/05/12、2023.05.12或20230512,这些格式如果不转换,MySQL不会把它们当作合法日期处理。
因此,在讨论var如何转date之前,需要先确认数据源是表字段还是用户变量。两者的转换写法基本相同,但用户变量需要注意作用域和NULL值处理,表字段则需要关注是否会产生隐式转换导致查询性能下降。
二、使用STR_TO_DATE函数进行灵活转换
STR_TO_DATE是MySQL中最常用的字符串转日期函数,它允许开发者按照指定的格式模板解析字符串。函数语法为STR_TO_DATE(str, format),其中str是待转换的字符串,format是格式模板。如果字符串与格式模板匹配,函数返回对应的DATE、DATETIME或TIME值;如果不匹配,则返回NULL。
格式模板由百分号开头的占位符组成。常用的占位符包括:%Y表示四位年份,%y表示两位年份,%m表示两位月份,%c表示数字月份(1到12),%d表示两位日期,%H表示24小时制小时,%i表示分钟,%s表示秒。例如字符串2023/05/12对应的格式模板为%Y/%m/%d,字符串20230512对应的格式模板为%Y%m%d。
下面用一个示例表演示不同格式的字符串如何转换为DATE:
CREATE TABLE var_demo (
id INT PRIMARY KEY AUTO_INCREMENT,
date_str VARCHAR(50)
);
INSERT INTO var_demo (date_str) VALUES
('2023/05/12'),
('2023.05.13'),
('20230514'),
('12-05-2023');
SELECT
id,
date_str,
STR_TO_DATE(date_str, '%Y/%m/%d') AS date_from_slash,
STR_TO_DATE(date_str, '%Y.%m.%d') AS date_from_dot,
STR_TO_DATE(date_str, '%Y%m%d') AS date_from_compact,
STR_TO_DATE(date_str, '%d-%m-%Y') AS date_from_euro
FROM var_demo;
从结果可以看到,只有与格式模板完全匹配的字符串才能被正确转换。假设一条记录的日期格式是2023/05/12,但使用了%Y-%m-%d模板去解析,STR_TO_DATE会返回NULL。因此使用该函数时,必须先明确字符串的真实格式。
另外,STR_TO_DATE在遇到非法日期时也会返回NULL,例如STR_TO_DATE('2023-02-30', '%Y-%m-%d')会返回NULL,因为2月没有30日。配合严格模式可以让这类错误暴露出来,便于排查数据质量问题。
三、使用CAST和CONVERT处理标准格式字符串
如果VARCHAR字段中保存的日期字符串已经是标准的YYYY-MM-DD格式,那么直接使用CAST或CONVERT函数会更加简洁。这两个函数的作用是进行数据类型转换,语法分别为CAST(expr AS DATE)和CONVERT(expr, DATE)。
例如下面的查询可以直接把标准格式的字符串转换为DATE类型:
SELECT
CAST('2023-05-12' AS DATE) AS cast_date,
CONVERT('2023-05-12', DATE) AS convert_date;
这两种写法返回的结果都是2023-05-12。需要注意的是,CAST和CONVERT并不像STR_TO_DATE那样支持自定义格式模板,它们要求输入字符串必须能被MySQL直接识别为日期。如果字符串是2023/05/12,CAST('2023/05/12' AS DATE)在默认日期格式下会返回NULL,因为斜杠分隔的格式不一定与当前会话的日期格式一致。
因此,CAST和CONVERT适合用于清洗后已经规范化的数据。对于来源不固定、格式多样的日期字符串,更稳妥的做法是先使用STR_TO_DATE显式指定格式,或者先用字符串函数清洗成标准格式再强转。
四、转换用户变量@var的完整示例
用户变量@var在存储过程、触发器和批处理脚本中经常出现。如果@var中保存的是日期字符串,转换为DATE的方式与字段转换一致。下面通过一个完整的会话示例展示转换过程:
-- 定义用户变量并赋值为日期字符串
SET @var = '2023/05/12 14:30:00';
-- 转换为DATE,只保留年月日
SELECT STR_TO_DATE(@var, '%Y/%m/%d %H:%i:%s') AS full_date,
STR_TO_DATE(SUBSTRING(@var, 1, 10), '%Y/%m/%d') AS date_only;
-- 使用CAST处理标准格式变量
SET @var = '2023-05-12';
SELECT CAST(@var AS DATE) AS cast_from_var;
如果用户变量可能为NULL,直接转换仍然返回NULL,这在业务上可能需要兜底处理。可以使用COALESCE函数为NULL结果提供一个默认日期,例如:
SET @var = NULL; SELECT COALESCE(STR_TO_DATE(@var, '%Y-%m-%d'), '1970-01-01') AS safe_date;
这个示例在@var为NULL或格式不匹配导致转换失败时,会返回1970-01-01作为兜底值。需要注意,业务中是否使用默认日期要根据实际场景决定,有时返回NULL让上层逻辑处理反而更合适。
五、常见错误与最佳实践
第一类常见错误是忽略格式符的大小写。例如%Y表示四位年份,而%y表示两位年份。如果字符串年份是2023,却使用%y解析,可能得到错误的结果或NULL。第二类错误是在WHERE条件中直接对VARCHAR日期字段使用字符串比较,比如WHERE date_str BETWEEN '2023-01-01' AND '2023-12-31'。这种写法虽然表面上能返回结果,但比较的是字符串字典序,不是真正的日期大小,而且无法利用该列上的普通索引进行范围扫描,容易引发全表扫描。
第三个常见误区是忽视时区问题。DATE类型本身没有时区概念,但如果源数据包含DATETIME字符串且带时区偏移,直接取前10位可能丢失小时影响日期。应该先明确业务是只按日期维度统计,还是需要保留完整时间。
最佳实践方面,最根本的解决方案是在表设计阶段就把日期字段定义成DATE或DATETIME类型,避免在应用层存储日期字符串。如果历史数据已经以VARCHAR形式存在,可以创建生成列:ALTER TABLE var_demo ADD COLUMN date_col DATE AS (STR_TO_DATE(date_str, '%Y-%m-%d')) STORED;,这样既能保留原始字符串,又能通过生成列建立索引提升查询性能。
最后,转换失败返回NULL的问题建议通过数据校验、严格模式或COALESCE来处理。在批量导入数据前,可以使用SELECT ... WHERE STR_TO_DATE(date_str, '%Y-%m-%d') IS NULL找出所有无法转换的脏数据,清洗后再执行转换,避免业务运行中出现意外的空值。
MySQL日期转换STR_TO_DATEVARCHAR转DATE修改时间:2026-08-29 09:14:33