You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用TypeORM+Oracle批量插入2万条数据?

批量插入Oracle数据的TypeORM问题与解决

问题背景

需要用TypeORM向Oracle的USERS_CACHE表批量插入2万条数据,该操作每天执行1次或多次,希望通过批量插入提升效率。

错误场景

使用批量插入代码时触发Oracle错误:

ORA-01745: invalid host/bind variable name

执行的代码如下:

await AppDataSource.createQueryBuilder()
  .insert()
  .into(CacheUsersORM)
  .values(cacheusers)
  .execute();

排查发现cacheusers并非预期的实体对象数组,而是一个扁平的一维数组:

[
    "3E3F2BF1-AD4C-4903-993E-503E5AB3713C",
    "usr1",
    "ldapalias1",
    3,
    "CN=usr1, OU=Users, DC=ad, DC=ent, DC=example, DC=com",
    "7AECDFA9-2B7B-419F-8BA6-55810B731EC1",
    "usr2",
    "ldapalias1",
    3,
    "CN=usr2, OU=Users, DC=ad, DC=ent, DC=example, DC=com"
]

而改用循环单条插入虽然能成功,但本地测试耗时超10分钟,效率极低:

for (const singleuser of cacheusers) {
    await AppDataSource.createQueryBuilder()
      .insert()
      .into(CacheUsersORM)
      .values(singleuser)
      .execute();
}

对应的TypeORM实体定义:

import {
  Column,
  Entity,
  PrimaryColumn,
  Unique,
} from "typeorm";

@Entity("USERS_CACHE")
@Unique("USERSCACHE_UC", ["userName", "ldapContainerID"])
export class UsersCacheORM {
  @PrimaryColumn({
    name: "USERGUID",
    type: "nvarchar2",
    length: 36,
    primaryKeyConstraintName: "USERSCACHE_PK",
  })
  userGUID?: string;

  @Column({ name: "USERNAME", nullable: false, type: "varchar2", length: 256 })
  userName!: string;

  @Column({
    name: "LDAP_ALIAS",
    nullable: false,
    type: "varchar2",
    length: 256,
  })
  ldapAlias!: string;

  @Column({ name: "LDAP_CONTAINER_ID", nullable: false, type: "number" })
  ldapContainerID!: number;

  @Column({ name: "LDAP_DN", nullable: false, type: "varchar2", length: 4000 })
  ldapDN!: string;
}

问题根源

批量插入失败的核心是cacheusers格式错误:TypeORM的批量插入要求values参数必须是匹配实体结构的对象数组,但当前传入的是扁平一维数组,导致TypeORM无法正确映射数据库字段,生成了错误的SQL绑定变量,最终触发Oracle的ORA-01745错误。

解决方案

1. 转换数据格式

先把扁平数组转换成符合UsersCacheORM结构的对象数组(每5个元素对应一个用户的5个字段):

// 将扁平数组转为实体对象数组
const formattedUsers = [];
for (let i = 0; i < cacheusers.length; i += 5) {
  formattedUsers.push({
    userGUID: cacheusers[i],
    userName: cacheusers[i + 1],
    ldapAlias: cacheusers[i + 2],
    ldapContainerID: cacheusers[i + 3],
    ldapDN: cacheusers[i + 4]
  });
}

2. 分批次批量插入

Oracle对单条SQL的绑定变量数量有限制,一次性插入2万条数据可能超出上限,建议分批次插入(比如每批次1000条):

const batchSize = 1000;
for (let i = 0; i < formattedUsers.length; i += batchSize) {
  const batch = formattedUsers.slice(i, i + batchSize);
  await AppDataSource.createQueryBuilder()
    .insert()
    .into(UsersCacheORM)
    .values(batch)
    .execute();
}

3. 备选方案:用EntityManager.save批量插入

如果QueryBuilder方式仍有问题,可以改用EntityManager的save方法,TypeORM会自动处理批量逻辑:

const batchSize = 1000;
for (let i = 0; i < formattedUsers.length; i += batchSize) {
  const batch = formattedUsers.slice(i, i + batchSize);
  await AppDataSource.manager.save(UsersCacheORM, batch);
}

效果说明

转换格式并采用分批次批量插入后,2万条数据的插入耗时可大幅降低至数分钟内(具体时间取决于数据库性能)。

内容的提问来源于stack exchange,提问作者Ranjeet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 08:48:11