种子数据
本指南介绍如何使用 Prisma Client 和 Prisma ORM 集成的种子数据功能来为您的数据库播种种子数据。种子数据允许您在数据库中一致地重新创建相同的数据,并且可用于
- 使用应用程序启动所需的数据填充您的数据库,例如默认语言或货币。
- 提供基本数据以在开发环境中验证和使用您的应用程序。如果您使用 Prisma Migrate,这尤其有用,因为有时需要重置开发数据库。
如何在 Prisma ORM 中为数据库播种种子数据
Prisma ORM 的集成种子数据功能需要在 package.json
文件的 "prisma"
键中的 "seed"
键中提供一个命令。这可以是任何命令,prisma db seed
将执行它。在本指南中,并且作为默认值,我们建议在项目的 prisma/
文件夹内编写一个种子数据脚本,并使用该命令启动它。
- TypeScript
- JavaScript
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
使用 TypeScript 时,ts-node
默认执行转译和类型检查;可以使用以下标志 --transpile-only
禁用类型检查。
示例:"seed": "ts-node --transpile-only prisma/seed.ts"
这对于减少内存使用量(RAM)和提高种子数据脚本的执行速度很有用。
"prisma": {
"seed": "node prisma/seed.js"
},
与 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 dev
或 prisma migrate reset
时,可以传递 --skip-seed
标志。
种子数据脚本示例
这里我们建议针对不同情况的一些特定种子数据脚本。您可以随意自定义这些脚本,但也可以按此处所示使用它们。
使用 TypeScript 或 JavaScript 为数据库播种种子数据
- TypeScript
- JavaScript
-
创建一个名为
seed.ts
的新文件。此文件可以放置在项目文件夹结构中的任何位置。下面的示例将其放置在/prisma
文件夹中。 -
在
seed.ts
文件中,导入 Prisma Client,初始化它并创建一些记录。例如,使用以下具有User
和Post
模型的 Prisma 模式schema.prismamodel 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.tsimport { 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)
}) -
添加
typescript
、ts-node
和@types/node
开发依赖项npm install -D typescript ts-node @types/node
-
将
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"
}, -
要为数据库播种种子数据,请运行
db seed
CLI 命令npx prisma db seed
-
创建一个名为
seed.js
的新文件。此文件可以放置在项目文件夹结构中的任何位置。下面的示例将其放置在/prisma
文件夹中。 -
在
seed.js
文件中,导入 Prisma Client,初始化它并创建一些记录。例如,使用以下具有User
和Post
模型的 Prisma 模式schema.prismagenerator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
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.js
文件中创建一些新的用户和帖子seed.jsconst { PrismaClient } = require('@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)
}) -
将
prisma.seed
添加到您的package.json
文件中package.json{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "node prisma/seed.js"
}
} -
要为数据库播种种子数据,请运行
db seed
CLI 命令npx prisma db seed
通过原始 SQL 查询为数据库播种种子数据
您还可以使用原始 SQL 查询来为数据库播种种子数据。
虽然您可以为此使用纯文本 .sql
文件(例如数据转储),但通常更容易将这些原始查询(如果它们很短)放置在 seed.js
文件中,因为它可以避免您处理数据库连接字符串和创建对 psql
等二进制文件的依赖关系的麻烦。
要为上面的 schema.prisma
添加其他数据,请将以下内容添加到 seed.js
(或 seed.ts
)文件中
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 调用,例如对文件末尾进行以下更改
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)为数据库播种种子数据。
- Go
- SQL
以下示例在与 seed.sh
相同的文件夹中运行 Go 脚本
#!/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/
以下示例使用 psql 在与 seed.sh
相同的文件夹中运行 SQL 脚本
#!/bin/sh
# -e Exit immediately when a command returns a non-zero status.
# -x Print commands before they are executed
set -ex
# Seeding command
psql file.sql
用户定义的参数
此功能自版本 4.15.0 及更高版本起可用。
prisma db seed
允许您在种子数据文件中定义自定义参数,您可以将这些参数传递给 prisma db seed
命令。例如,您可以定义自己的参数以针对不同的环境播种不同的数据,或在某些表中部分播种数据。
这是一个种子数据文件示例,它定义了一个自定义参数以在不同的环境中播种不同的数据
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 集成以为您数据库播种种子数据的其他工具(非详尽列表)