MySQL、PostgreSQL、SQL Server 的批量导入(LOAD DATA、COPY、BULK INSERT)均不触发列的 DEFAULT 值,缺失字段会被视为 NULL 或报错,必须显式赋值(如 SET created_at = NOW())或预处理 CSV;时间格式不一致需清洗或条件转换。
MySQL 导入 CSV 时 created_at 字段没填,但表定义了 DEFAULT CURRENT_TIMESTAMP 为什么还是报错?
因为 load data infile 默认把缺失列当作 null,而如果该字段是 not null 且没显式指定值,即使有 default,mysql 也不会自动触发默认值——除非你告诉它“这一列跳过”。
- 必须在
LOAD DATA语句末尾用SET子句显式赋值:SET created_at = NOW() - 或者在字段列表中把
created_at写成@dummy占位,再SET created_at = NOW() - 如果 CSV 里本就有时间列(比如第5列),可直接映射:
SET created_at = STR_TO_DATE(@col5, '%Y-%m-%d %H:%i:%s') -
IGNORE或REPLACE不影响默认值行为,该设还得设
PostgreSQL 的 COPY 怎么让缺失的 updated_at 自动填 NOW()?
PostgreSQL 的 COPY 更严格:它不支持 SET,也不解析 DEFAULT 表达式。缺失字段就真缺失,不会 fallback 到默认值。
- 最稳的办法:导入前用
sed或脚本给每行末尾补一个(对应updated_at字段),或用awk插入当前时间字符串 - 次选:改用
INSERT ... SELECT+generate_series或临时表,但性能差很多 - 别指望
DEFAULT在COPY里生效——哪怕字段声明了DEFAULT NOW(),只要 CSV 没提供值,就会报null value in column ... violates not-null constraint - 注意时区:
NOW()是 server 时区,如果 CSV 时间是 UTC,而字段类型是TIMESTAMP WITH TIME ZONE,得手动转:SET updated_at = (NOW() AT TIME ZONE 'UTC')
SQL Server 的 BULK INSERT 遇到 datetime2 缺失,GETDATE() 默认值为啥不生效?
和 MySQL 类似,BULK INSERT 把未提供的列当 NULL,即使定义了 DEFAULT GETDATE(),也只对普通 INSERT 有效。
- 必须用格式文件(
.fmt)明确标出哪些字段要跳过,并在INSERT后用UPDATE补时间——但批量更新可能锁表 - 更实用:先
BULK INSERT到带NULL允许的临时表,再INSERT INTO real_table SELECT ..., ISNULL(updated_at, GETDATE()) FROM temp - 如果 CSV 有空字段(比如
,,),SQL Server 可能报Unexpected end of file encountered,得确认FIELDS TERMINATED BY和ROWTERMINATOR是否匹配换行符 -
KEEPNULLS选项会让默认值彻底失效;不用它,但缺失仍不算NULL——所以本质还是得预处理或后处理
通用避坑:CSV 时间格式不一致导致 STR_TO_DATE 或 TO_TIMESTAMP 失败
就算你写了 SET created_at = STR_TO_DATE(@col3, '%m/%d/%Y %h:%i %p'),只要某行是 2024-03-15 14:30:00,整批就挂。
- MySQL:用
IF+ 多个STR_TO_DATE尝试,最后 fallback 到NOW():SET created_at = IF(@col3 REGEXP '^\d{4}-\d{2}-\d{2}', STR_TO_DATE(@col3, '%Y-%m-%d %H:%i:%s'), IF(@col3 REGEXP '^\d{1,2}/\d{1,2}/\d{4}', STR_TO_DATE(@col3, '%m/%d/%Y %h:%i %p'), NOW())) - PostgreSQL:用
COALESCE+ 多个TO_TIMESTAMP,但注意TO_TIMESTAMP报错会中断整个COPY,所以必须先清洗 - 真正省事的做法:用 Python / awk 预处理 CSV,统一转成 ISO 格式(
2024-03-15T14:30:00),数据库原生支持最好 - 别依赖客户端时区输出——导出 CSV 的机器时区和 DB 服务器时区不一致,
NOW()值就不可控











