数据播种
本指南介绍了如何使用 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
的上下文中交互式地重置数据库——例如,由于迁移历史冲突或数据库 schema 漂移。 - 数据库实际上是由
prisma migrate dev
创建的,因为它之前不存在。
当您希望在不播种的情况下使用 prisma migrate dev
或 prisma migrate reset
时,可以传递 --skip-seed
标志。
播种脚本示例
这里我们为不同情况提供了一些特定的播种脚本。您可以随意自定义它们,也可以按此处所示使用它们。
使用 TypeScript 或 JavaScript 播种数据库
- TypeScript
- JavaScript
-
创建一个名为
seed.ts
的新文件。它可以放在项目文件夹结构的任何位置。下面的示例将其放在/prisma
文件夹中。 -
在
seed.ts
文件中,导入 Prisma Client,初始化它并创建一些记录。例如,以下 Prisma schema 包含User
和Post
模型: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: '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)
}) -
添加
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,初始化它并创建一些记录。例如,以下 Prisma schema 包含User
和Post
模型: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: '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)
}) -
将
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, 'foo@example.com', '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 集成到开发工作流中以播种数据库的其他工具的非详尽列表: