跳至主要内容

种子数据

本指南介绍如何使用 Prisma Client 和 Prisma ORM 集成的种子数据功能来为您的数据库播种种子数据。种子数据允许您在数据库中一致地重新创建相同的数据,并且可用于

  • 使用应用程序启动所需的数据填充您的数据库,例如默认语言或货币。
  • 提供基本数据以在开发环境中验证和使用您的应用程序。如果您使用 Prisma Migrate,这尤其有用,因为有时需要重置开发数据库。

如何在 Prisma ORM 中为数据库播种种子数据

Prisma ORM 的集成种子数据功能需要在 package.json 文件的 "prisma" 键中的 "seed" 键中提供一个命令。这可以是任何命令,prisma db seed 将执行它。在本指南中,并且作为默认值,我们建议在项目的 prisma/ 文件夹内编写一个种子数据脚本,并使用该命令启动它。


"prisma": {
"seed": "ts-node prisma/seed.ts"
},

信息

使用 TypeScript 时,ts-node 默认执行转译和类型检查;可以使用以下标志 --transpile-only 禁用类型检查。

示例:"seed": "ts-node --transpile-only prisma/seed.ts"

这对于减少内存使用量(RAM)和提高种子数据脚本的执行速度很有用。

与 Prisma Migrate 集成的种子数据

使用 Prisma ORM 时,数据库种子数据有两种方式:使用 prisma db seed 手动播种,以及在 prisma migrate reset 和(在某些情况下)prisma migrate dev 中自动播种。

使用 prisma db seed 可以决定何时调用种子数据命令。例如,它可以用于测试设置或准备新的开发环境。

Prisma Migrate 也与您的种子数据无缝集成,假设您遵循下面部分中的步骤。当 Prisma Migrate 重置开发数据库时,会自动触发种子数据。

Prisma Migrate 在以下情况下重置数据库并触发种子数据

  • 您手动运行 prisma migrate reset CLI 命令。
  • 在使用 prisma migrate dev 的上下文中以交互方式重置数据库 - 例如,由于迁移历史冲突或数据库模式漂移导致。
  • prisma migrate dev 实际上创建了数据库,因为它之前不存在。

当您想在不播种种子数据的情况下使用 prisma migrate devprisma migrate reset 时,可以传递 --skip-seed 标志。

种子数据脚本示例

这里我们建议针对不同情况的一些特定种子数据脚本。您可以随意自定义这些脚本,但也可以按此处所示使用它们。

使用 TypeScript 或 JavaScript 为数据库播种种子数据

  1. 创建一个名为 seed.ts 的新文件。此文件可以放置在项目文件夹结构中的任何位置。下面的示例将其放置在 /prisma 文件夹中。

  2. seed.ts 文件中,导入 Prisma Client,初始化它并创建一些记录。例如,使用以下具有 UserPost 模型的 Prisma 模式

    schema.prisma
    model User {
    id Int @id @default(autoincrement())
    email String @unique
    name String
    posts Post[]
    }

    model Post {
    id Int @id @default(autoincrement())
    title String
    content String
    published Boolean
    user User @relation(fields: [userId], references: [id])
    userId Int
    }

    在您的 seed.ts 文件中创建一些新的用户和帖子

    seed.ts
    import { PrismaClient } from '@prisma/client'
    const prisma = new PrismaClient()
    async function main() {
    const alice = await prisma.user.upsert({
    where: { email: '[email protected]' },
    update: {},
    create: {
    email: '[email protected]',
    name: 'Alice',
    posts: {
    create: {
    title: 'Check out Prisma with Next.js',
    content: 'https://prisma.org.cn/nextjs',
    published: true,
    },
    },
    },
    })
    const bob = await prisma.user.upsert({
    where: { email: '[email protected]' },
    update: {},
    create: {
    email: '[email protected]',
    name: 'Bob',
    posts: {
    create: [
    {
    title: 'Follow Prisma on Twitter',
    content: 'https://twitter.com/prisma',
    published: true,
    },
    {
    title: 'Follow Nexus on Twitter',
    content: 'https://twitter.com/nexusgql',
    published: true,
    },
    ],
    },
    },
    })
    console.log({ alice, bob })
    }
    main()
    .then(async () => {
    await prisma.$disconnect()
    })
    .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
    })
  3. 添加 typescriptts-node@types/node 开发依赖项

    npm install -D typescript ts-node @types/node
  1. prisma.seed 字段添加到您的 package.json 文件中

    package.json
    {
    "name": "my-project",
    "version": "1.0.0",
    "prisma": {
    "seed": "ts-node prisma/seed.ts"
    },
    "devDependencies": {
    "@types/node": "^14.14.21",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
    }
    }

    某些项目可能需要您添加编译选项。例如,当使用 Next.js 时,您将如下设置种子数据脚本

    package.json
    "prisma": {
    "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
    },
  2. 要为数据库播种种子数据,请运行 db seed CLI 命令

    npx prisma db seed

通过原始 SQL 查询为数据库播种种子数据

您还可以使用原始 SQL 查询来为数据库播种种子数据。

虽然您可以为此使用纯文本 .sql 文件(例如数据转储),但通常更容易将这些原始查询(如果它们很短)放置在 seed.js 文件中,因为它可以避免您处理数据库连接字符串和创建对 psql 等二进制文件的依赖关系的麻烦。

要为上面的 schema.prisma 添加其他数据,请将以下内容添加到 seed.js(或 seed.ts)文件中

seed.js
async function rawSql() {
const result = await prisma.$executeRaw`INSERT INTO "User" ("id", "email", "name") VALUES (3, '[email protected]', 'Foo') ON CONFLICT DO NOTHING;`
console.log({ result })
}

并将此函数链接到 promise 调用,例如对文件末尾进行以下更改

seed.js
main()
.then(rawSql)
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})

通过任何语言(使用 Bash 脚本)为数据库播种种子数据

除了 TypeScript 和 JavaScript 之外,您还可以使用 Bash 脚本(seed.sh)以其他语言(如 Go 或纯 SQL)为数据库播种种子数据。


以下示例在与 seed.sh 相同的文件夹中运行 Go 脚本


seed.sh
#!/bin/sh
# -e Exit immediately when a command returns a non-zero status.
# -x Print commands before they are executed
set -ex
# Seeding command
go run ./seed/

用户定义的参数

此功能自版本 4.15.0 及更高版本起可用。

prisma db seed 允许您在种子数据文件中定义自定义参数,您可以将这些参数传递给 prisma db seed 命令。例如,您可以定义自己的参数以针对不同的环境播种不同的数据,或在某些表中部分播种数据。

这是一个种子数据文件示例,它定义了一个自定义参数以在不同的环境中播种不同的数据

"seed.js"
import { parseArgs } from 'node:util'

const options = {
environment: { type: 'string' },
}

async function main() {
const {
values: { environment },
} = parseArgs({ options })

switch (environment) {
case 'development':
/** data for your development */
break
case 'test':
/** data for your test environment */
break
default:
break
}
}

main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})

然后,您可以通过添加 分隔符-- —,后跟您的自定义参数,在使用 prisma db seed 时提供 environment 参数

npx prisma db seed -- --environment development

更进一步

以下列出了您可以在开发工作流中与 Prisma ORM 集成以为您数据库播种种子数据的其他工具(非详尽列表)