跳到主要内容

数据填充

本指南介绍如何使用 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 默认执行转译和类型检查;可以使用以下 flag --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 的上下文中以交互方式重置数据库 - 例如,由于迁移历史冲突或数据库 schema 漂移。
  • 数据库实际是由 prisma migrate dev 创建的,因为它之前不存在。

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

示例种子脚本

在此,我们为不同情况提供了一些特定的种子脚本建议。您可以随意自定义这些脚本,但也可以直接使用此处提供的示例:

使用 TypeScript 或 JavaScript 填充数据库

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

  2. seed.ts 文件中,导入 Prisma Client,对其进行初始化并创建一些记录。例如,考虑以下包含 UserPost 模型的 Prisma schema:

    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: 'alice@prisma.io' },
    update: {},
    create: {
    email: 'alice@prisma.io',
    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: 'bob@prisma.io' },
    update: {},
    create: {
    email: 'bob@prisma.io',
    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, 'foo@example.com', '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 集成以填充数据库的非穷尽工具列表: