TypeORM批量插入Oracle时PrimaryGeneratedColumn('increment')失效问题
TypeORM批量插入Oracle时ORA-01400错误的解决方法
问题背景
使用TypeORM 0.3.17连接Oracle 19c,定义Zone实体如下:
export class Zone extends BaseEntity { @PrimaryGeneratedColumn("increment") id: number @Column({nullable: false, unique: true, length: 100}) name: string }
通过zones.json批量插入数据时执行以下代码:
import zonesJSON from "./zones.json" async function populateZones(): Promise<Zone[]> { let savedZones: Zone[] = await Zone.find(); if (savedZones.length === 0) { savedZones = Zone.create(zonesJson as object[]) as Zone[]; await Zone.insert(savedZones); } return savedZones; }
触发错误:
QueryFailedError: ORA-01400: cannot insert NULL into (<schema>."zone"."id")
原因是TypeORM生成的SQL会将id设为NULL插入:
INSERT INTO <schema>."zone"("id", "name") SELECT NULL, :1 FROM DUAL UNION ALL SELECT NULL, :2 FROM DUAL -- PARAMETERS: ["ZONA 1","ZONA 2"]
而Oracle表的id列是GENERATED BY DEFAULT定义的,仅在不提供该字段时自动生成值,传入NULL会触发错误。
解决方法
1. 修改实体列定义,排除id字段的插入
在@PrimaryGeneratedColumn中添加insert: false选项,告诉TypeORM插入操作时不包含该字段:
export class Zone extends BaseEntity { @PrimaryGeneratedColumn("increment", { insert: false }) id: number @Column({nullable: false, unique: true, length: 100}) name: string }
这样TypeORM生成的SQL会省略id字段,Oracle的标识列会自动生成值。
2. 修改Oracle表的标识列属性
执行DDL语句将id列改为GENERATED BY DEFAULT ON NULL,允许传入NULL时自动生成值:
ALTER TABLE zone MODIFY id GENERATED BY DEFAULT ON NULL AS IDENTITY;
此方式适配TypeORM当前生成的SQL,无需修改代码或实体定义。
3. 调整插入逻辑,直接使用原始数据
跳过Zone.create步骤,直接将原始JSON数组传入Zone.insert,TypeORM会自动忽略未提供的id字段:
import zonesJSON from "./zones.json" async function populateZones(): Promise<Zone[]> { let savedZones: Zone[] = await Zone.find(); if (savedZones.length === 0) { await Zone.insert(zonesJSON); savedZones = await Zone.find(); // 插入后重新查询获取带id的实体 } return savedZones; }
这种方式避免了Zone.create生成包含id为undefined/null的对象,确保插入SQL不包含id字段。
内容的提问来源于stack exchange,提问作者Nicolás Bravo
相关产品推荐
相关产品推荐

