跳至主内容区

使用 QueryBuilder 插入数据

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

你可以使用 QueryBuilder 创建 INSERT 查询。 示例:

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values([
{ firstName: "Timber", lastName: "Saw" },
{ firstName: "Phantom", lastName: "Lancer" },
])
.execute()

这是在性能方面最有效的向数据库中插入行的方法,你也可以用这种方式执行批量插入。

原生 SQL 支持

在某些情况下执行 SQL 查询时,需要使用函数式值:

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: () => "CONCAT('S', 'A', 'W')",
})
.execute()

警告:使用原生 SQL 时,请确保正确清理值以防止 SQL 注入。

冲突时更新值

当插入值因现有数据产生冲突时,可使用 orUpdate 函数更新冲突目标的特定值。

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: "Saw",
externalId: "abc123",
})
.orUpdate(["firstName", "lastName"], ["externalId"])
.execute()

带条件的冲突时更新值(Postgres、Oracle、MSSQL、SAP HANA)

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: "Saw",
externalId: "abc123",
})
.orUpdate(["firstName", "lastName"], ["externalId"], {
overwriteCondition: {
where: {
firstName: Equal("Phantom"),
},
},
})
.execute()

插入时忽略错误(MySQL)或不执行操作(Postgres、Oracle、MSSQL、SAP HANA)

当插入值因现有数据或无效数据产生冲突时,使用 orIgnore 函数可抑制错误并仅插入有效数据行。

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: "Saw",
externalId: "abc123",
})
.orIgnore()
.execute()

值未更改时跳过数据更新(Postgres、Oracle、MSSQL、SAP HANA)

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: "Saw",
externalId: "abc123",
})
.orUpdate(["firstName", "lastName"], ["externalId"], {
skipUpdateIfNoValuesChanged: true,
})
.execute()

使用部分索引(Postgres)

await dataSource
.createQueryBuilder()
.insert()
.into(User)
.values({
firstName: "Timber",
lastName: "Saw",
externalId: "abc123",
})
.orUpdate(["firstName", "lastName"], ["externalId"], {
skipUpdateIfNoValuesChanged: true,
indexPredicate: "date > 2020-01-01",
})
.execute()

从 SELECT 查询插入数据

通过 valuesFromSelect() 方法配合 SELECT 查询,可将数据从一个表插入到另一个表。这会生成 INSERT INTO ... SELECT FROM 语句,适用于数据迁移、归档或在表之间复制数据。

直接使用 SelectQueryBuilder

// Create a select query to get the source data
const selectQuery = dataSource
.createQueryBuilder()
.select(["user.firstName", "user.lastName"])
.from(User, "user")
.where("user.isActive = :isActive", { isActive: true })

// Insert the selected data into another table
await dataSource
.createQueryBuilder()
.insert()
.into(ArchivedUser, ["firstName", "lastName"])
.valuesFromSelect(selectQuery)
.execute()

使用回调函数

也可通过回调函数构建 SELECT 查询:

await dataSource
.createQueryBuilder()
.insert()
.into(ArchivedUser, ["firstName", "lastName", "archivedAt"])
.valuesFromSelect((qb) =>
qb
.select(["user.firstName", "user.lastName", "NOW()"])
.from(User, "user")
.where("user.deletedAt IS NOT NULL"),
)
.execute()

使用连接(joins)

可在 SELECT 查询中使用连接(joins)来合并多个表的数据:

await dataSource
.createQueryBuilder()
.insert()
.into(UserReport, ["userName", "orderCount"])
.valuesFromSelect((qb) =>
qb
.select(["user.name", "COUNT(order.id)"])
.from(User, "user")
.leftJoin("user.orders", "order")
.groupBy("user.id"),
)
.execute()

注意: 使用 valuesFromSelect() 时,实体监听器和订阅器(@BeforeInsert@AfterInsert)不会被调用,因为在插入操作期间不会创建实体实例。

注意: updateEntity 选项在使用 valuesFromSelect() 时无效,因为没有实体实例可供更新。