需用str_to_date()显式转换日期格式,如set order_date = str_to_date(trim(@date_str), '%y/%m/%d'),并确保格式匹配、清除空格、过滤无效值,否则默认转为0000-00-00。
load data infile 读入的日期变成 0000-00-00 怎么办
MySQL 默认不自动解析形如 "2023/05/12"、"12-May-2023" 或 "20230512" 的字符串为日期,LOAD DATA INFILE 会直接把它们当无效值塞成 0000-00-00。
根本原因不是数据错,是 MySQL 没看到“这是日期”,它只认严格符合 YYYY-MM-DD 或 YYYYMMDD 格式的字符串(且在 DATE 列上)。
解决办法是用 SET 子句配合 STR_TO_DATE() 显式转换:
LOAD DATA INFILE '/tmp/data.csv' INTO TABLE orders FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' (@date_str, amount, product) SET order_date = STR_TO_DATE(@date_str, '%Y/%m/%d');
-
@date_str是用户变量,临时存下原始字段值 -
STR_TO_DATE()第二个参数必须和 CSV 中实际格式完全一致:比如"12/May/2023"要写'%d/%b/%Y',"20230512"对应'%Y%m%d' - 如果某行日期格式不统一(比如混了
"2023-05-12"和"12-05-2023"),STR_TO_DATE()会返回NULL,得先清洗数据
Python pandas read_csv 后 to_sql 写入 MySQL,日期列变 None 或报错
pandas 默认把含斜杠、短横、中文的日期字符串读成 object 类型,不是 datetime64;直接传给 to_sql(),SQLAlchemy 可能把它当字符串或 None 处理,导致 MySQL 插入失败或写成 0000-00-00。
关键动作是:读取时就指定 parse_dates,并强制转成标准 datetime:
df = pd.read_csv('data.csv', parse_dates=['order_date'],
date_parser=lambda x: pd.to_datetime(x, format='%Y/%m/%d', errors='coerce'))
-
format参数越明确越好,比让 pandas 自动推断快且稳;不确定格式时用errors='coerce'把错的转成NaT,别让它崩 - 入库前检查:
df['order_date'].dt.strftime('%Y-%m-%d')看是否全为标准格式;有NaT就得决定是删掉还是补默认值 - MySQL 连接要用
dtype={'order_date': sqlalchemy.types.DATE}显式声明类型,避免 SQLAlchemy 自作主张映射成字符串
INSERT INTO ... SELECT 从临时表导入,日期字段仍是字符串
如果先用 CREATE TEMPORARY TABLE 建了个宽泛的 TEXT 或 VARCHAR 表存原始 CSV 数据,再想用 INSERT INTO target_table SELECT ... 导过去,日期列会原样搬运——MySQL 不会在 SELECT 过程中自动类型转换。
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
必须在 SELECT 里做转换:
INSERT INTO orders (order_date, amount) SELECT STR_TO_DATE(raw_date, '%d-%b-%Y'), amount FROM temp_import WHERE raw_date IS NOT NULL AND raw_date != '';
-
STR_TO_DATE()返回NULL时整行会被跳过(除非你加IFNULL(..., '1970-01-01')) - WHERE 条件很重要:空字符串、空格、"N/A" 这类非日期值不拦住,
STR_TO_DATE()全返回NULL,最后可能插了一堆0000-00-00 - 注意时区:如果原始数据是带时间的(如
"2023-05-12 14:30:00"),而目标列是DATE,STR_TO_DATE()仍可工作,但建议用DATETIME列接收再截断,更可控
不同地区日期格式(如 DD/MM/YYYY)导致误解析
欧洲常见 "15/04/2023"(15号4月),MySQL 默认按 YY-MM-DD 解析会当成 2023年15月——非法,结果变 0000-00-00。
不能靠改 MySQL 全局设置(如 date_format),它对 STR_TO_DATE() 无效;唯一靠谱的是在转换函数里写死格式:
- 明确是日/月/年:用
STR_TO_DATE(@d, '%d/%m/%Y') - 不确定是月/日/年还是日/月/年?别硬猜,先用 Python 或 shell 预处理统一成
YYYY-MM-DD格式再导入 - MySQL 8.0+ 支持
DATE_FORMAT()但它是输出函数,不解决输入解析问题 - 最隐蔽的坑:CSV 里日期字段前后有不可见空格(
" 15/04/2023 "),STR_TO_DATE()直接失败,务必先TRIM():
SET order_date = STR_TO_DATE(TRIM(@date_str), '%d/%m/%Y');
格式不匹配、空格、NULL 值、混合格式——这四点漏掉任何一点,日期就会静默变成 0000-00-00。别指望 MySQL 自己“猜对”,它只信你写的格式字符串。










