TypeORM生成MySQL迁移:如何将createdAt/updatedAt设为timestamp并解决错误
我在项目中使用MySQL + TypeORM,定义了如下实体:
export const CompanyRadarTypeEntity = new EntitySchema<ICompanyRadarTypeEntity>({ name: 'companyRadarType', tableName: 'companyRadarType', columns: { idCompanyRadarType: { type: Number, primary: true, generated: true, }, type: { type: String, }, idCompany: { type: Number, }, createdAt: { type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', nullable: false, createDate: true, }, updatedAt: { type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', nullable: false, updateDate: true, }, }, relations: { company: { type: 'many-to-one', target: 'company', joinColumn: { name: 'idCompany', referencedColumnName: 'idCompany', }, }, companyRadars: { type: 'one-to-many', target: 'companyRadar', inverseSide: 'companyRadarType', }, }, });
使用TypeORM生成迁移后,得到如下SQL:
await queryRunner.query(` CREATE TABLE \`companyRadarType\` ( \`idCompanyRadarType\` int NOT NULL AUTO_INCREMENT, \`type\` varchar(255) NOT NULL, \`idCompany\` int NOT NULL, \`createdAt\` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, \`updatedAt\` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (\`idCompanyRadarType\`) ) ENGINE = InnoDB `);
执行迁移时触发错误:
Error during migration run: QueryFailedError: ER_INVALID_DEFAULT: Invalid default value for 'createdAt'
若移除实体中的createDate: true和updateDate: true,字段类型虽为timestamp,但updatedAt会丢失ON UPDATE CURRENT_TIMESTAMP的自动更新逻辑。
解决方案
方法1:调整实体字段的默认值精度
MySQL严格模式下,timestamp(6)字段的默认值必须匹配精度。修改实体中createdAt和updatedAt的default配置,明确指定6位精度:
createdAt: { type: 'timestamp', default: () => 'CURRENT_TIMESTAMP(6)', // 和字段精度保持一致 nullable: false, createDate: true, }, updatedAt: { type: 'timestamp', default: () => 'CURRENT_TIMESTAMP(6)', nullable: false, updateDate: true, },
重新生成迁移后,SQL中的默认值会自动匹配字段精度,解决默认值无效的问题,同时保留createdAt和updatedAt的自动维护逻辑。
方法2:手动修正迁移文件的SQL
如果不想修改实体配置,直接编辑生成的迁移SQL,将createdAt的默认值改为CURRENT_TIMESTAMP(6):
`createdAt` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
修改后执行迁移即可正常运行,同时保留updatedAt的ON UPDATE逻辑。
方法3:调整MySQL的sql_mode配置(不推荐)
错误可能源于MySQL的sql_mode包含NO_ZERO_DATE或NO_ZERO_IN_DATE规则。可以临时修改会话级别的sql_mode:
SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
也可以修改MySQL配置文件(my.cnf/my.ini)中的sql_mode,移除NO_ZERO_DATE和NO_ZERO_IN_DATE后重启服务。但这种方法会降低数据校验的严格性,仅作为临时应急方案。
内容的提问来源于stack exchange,提问作者Gabriel Henrique

