创建数据:create 与嵌套写入
本教程共 54 篇 · 第 18 篇 · 更新于 2026-08-11 · 约 4 分钟阅读
本节目标:掌握单条、批量、带关系三种插入方式,理解嵌套写为什么是原子的。
写数据是 CRUD 的第一站。这一章看三种插入方式:单条、批量、带关系,以及它们各自的限制和陷阱。
创建单条记录
prisma.user.create 插入一条,返回完整记录:
const user = await prisma.user.create({
data: {
email: "elsa@prisma.io",
name: "Elsa",
},
});
data 的类型由 Schema 推导出来,叫 Prisma.UserCreateInput。字段名写错、类型不匹配,编译期就会报错,不用等运行时报 500。id 由数据库自动生成;带 @default 的字段可以不传,比如 createdAt 会自动填充当前时间。
批量创建:createMany
一次插入多条,返回 { count } 计数:
const result = await prisma.user.createMany({
data: [
{ email: "bob@prisma.io", name: "Bob" },
{ email: "ada@prisma.io", name: "Ada" },
],
skipDuplicates: true,
});
console.log(result.count); // 2
skipDuplicates 会跳过违反唯一约束的记录,重复执行不会报错,适合导入任务、种子数据这类可能重复的场景。注意它只在 PostgreSQL 和 MySQL 上可用,SQLite、SQL Server 不支持(MongoDB 整个 v7 不支持,留 v6.19)。
createMany 有两个限制:不能带关系字段;只返回计数,拿不到新记录。想拿回整批记录,用 createManyAndReturn(PostgreSQL、CockroachDB、SQLite 支持),还能配合 select 裁剪返回字段:
const users = await prisma.user.createManyAndReturn({
data: [{ email: "a@prisma.io" }, { email: "b@prisma.io" }],
select: { id: true, email: true },
});
嵌套写入:一条命令建出整棵树
create 里可以直接带关系字段,一条查询写完父、子、孙级数据:
const user = await prisma.user.create({
data: {
email: "yvette@prisma.io",
posts: {
create: [
{ title: "第一篇" },
{ title: "第二篇", categories: { create: { name: "日记" } } },
],
},
},
include: { posts: { include: { categories: true } } },
});
这一步同时写了 User、Post、Category 三张表。嵌套写入整体是一个事务:任何一步失败,全部回滚,不会留下「用户建好了、帖子没建完」的残局。
Note嵌套写是单条 create 自带的能力,不需要手动包 $transaction。原子性由 Prisma 保证。嵌套层数没有硬性限制,但嵌套过深会生成复杂 SQL、可读性差,层数多了考虑拆分查询。
connect:挂接已有记录
文章的作者已存在,用 connect 按唯一字段挂上:
await prisma.post.create({
data: {
title: "Hello",
author: { connect: { email: "elsa@prisma.io" } },
},
});
connect 可以用任何唯一字段:id、@unique 字段、复合唯一键。一对多关系还能一次挂多个:
await prisma.user.create({
data: {
email: "vlad@prisma.io",
posts: { connect: [{ id: 8 }, { id: 9 }] },
},
});
注意:connect 引用的记录必须真实存在,任何一个找不到都会报错。
connectOrCreate:挂接或新建
不确定记录是否存在时,先找、找不到就建。重复执行结果一致,天然幂等:
await prisma.post.create({
data: {
title: "Hello",
categories: {
connectOrCreate: [
{ where: { name: "react" }, create: { name: "react" } },
],
},
},
});
connectOrCreate 的 where 必须命中唯一约束,否则校验失败。它很适合打标签、建分类这类「有就用,没有就造」的场景。
重复插入会怎样
唯一约束冲突时,create 会抛 P2002 错误。批量导入场景想忽略重复,用 skipDuplicates;单条场景可以用 try/catch 捕获后走更新逻辑:
import { Prisma } from "../generated/prisma/client";
try {
await prisma.user.create({ data: { email: "dup@x.io" } });
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2002") {
// 处理重复:提示用户或改走更新
}
}
嵌套 create 与嵌套 createMany 怎么选
| 能力 | 嵌套 create | 嵌套 createMany |
|---|---|---|
| 继续嵌套更深的关系 | 支持 | 不支持 |
| 多对多关系 | 支持 | 不支持 |
| skipDuplicates | 不支持 | 支持 |
要建「用户 + 多篇帖子 + 每篇帖子的分类」这种三层结构,只能用嵌套 create。嵌套 createMany 适合批量塞一层子记录。
参考来源
- Prisma 官方文档:CRUD(Create)
- Prisma 官方文档:Relation queries(Nested writes)
- Mapagam:Working with Create Operations