
本文详解str_to_date函数中日期格式字符串(format string)必须与输入日期字符串的实际格式严格一致,否则将返回null;通过修正格式模板、避免sql注入、推荐使用预处理语句等方法,确保日期准确写入数据库。
本文详解str_to_date函数中日期格式字符串(format string)必须与输入日期字符串的实际格式严格一致,否则将返回null;通过修正格式模板、避免sql注入、推荐使用预处理语句等方法,确保日期准确写入数据库。
在MySQL中使用STR_TO_DATE()将字符串转换为日期类型时,一个常见却隐蔽的错误是:日期值成功插入但数据库中显示为NULL。根本原因并非SQL语法错误,而是STR_TO_DATE()的第二个参数——即格式模板(format string)——与传入的日期字符串实际格式不匹配。
例如,原始代码如下:
$query1 = "INSERT INTO checkup_form
SET checkup_date = STR_TO_DATE('" . $medical_date . "', '%d-%m-%Y'),
emp_id = '" . $id . "'";若此时$medical_date的值为 '2024/03/15'(格式为 YYYY/MM/DD),而格式模板却写成 '%d-%m-%Y'(期望输入是 DD-MM-YYYY),MySQL无法解析,STR_TO_DATE()将静默返回NULL,最终导致checkup_date列存入空值。
✅ 正确做法是:让格式模板精准描述输入字符串的结构。对照关系如下:
| 输入示例 | 正确格式模板 | 错误模板(常见误区) |
|---|---|---|
| '15-03-2024' | '%d-%m-%Y' | '%Y-%m-%d'(反向假设) |
| '2024/03/15' | '%Y/%m/%d' | '%d-%m-%Y'(混淆分隔符与顺序) |
| '15/Mar/2024' | '%d/%b/%Y' | '%d-%m-%Y'(忽略英文缩写) |
? 关键提醒:
- %Y 表示4位年份(如2024),%y 表示2位年份(如24);
- %m 是数字月份(01–12),%c 是无前导零的月份(1–12);
- %d 是带前导零的日(01–31),%e 是无前导零的日(1–31);
- 分隔符(/, -, ., 空格等)必须与输入字符串完全一致。
? 同时,上述PHP拼接SQL的方式存在严重SQL注入风险。强烈建议改用预处理语句(Prepared Statements):
// ✅ 推荐:使用PDO预处理(安全 + 类型明确)
$stmt = $pdo->prepare("INSERT INTO checkup_form (checkup_date, emp_id) VALUES (?, ?)");
$stmt->execute([
DateTime::createFromFormat('d-m-Y', $medical_date)?->format('Y-m-d') ?: null, // 应用层校验+标准化
$id
]);或在SQL层统一用STR_TO_DATE(仍需格式匹配):
$stmt = $pdo->prepare("INSERT INTO checkup_form (checkup_date, emp_id)
VALUES (STR_TO_DATE(?, '%d-%m-%Y'), ?)");
$stmt->execute([$medical_date, $id]);? 小结:
- STR_TO_DATE(str, format) 的 format 是描述输入,不是定义输出;
- 格式不匹配 → 返回 NULL → 列值为空,且无报错提示,极易被忽略;
- 始终验证 $medical_date 实际格式(可借助 var_dump($medical_date) 或正则预检);
- 摒弃字符串拼接SQL,优先采用参数化查询,兼顾安全性与可维护性。
遵循以上原则,即可彻底解决日期列存入NULL的问题,保障数据完整性与业务可靠性。










