首页 / Prisma ORM 入门教程 / 创建数据:create 与嵌套写入

Prisma ORM 入门教程

创建数据:create 与嵌套写入

本教程共 54 篇 · 第 18 篇 · 更新于 2026-08-11 · 约 4 分钟阅读

createcreateMany嵌套写入connectconnectOrCreate事务CRUD

本节目标:掌握单条、批量、带关系三种插入方式,理解嵌套写为什么是原子的。

写数据是 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