数据填充
本指南介绍如何使用 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
默认执行转译和类型检查;可以使用以下 flag --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,对其进行初始化并创建一些记录。例如,考虑以下包含User
和Post
模型的 Prisma schema: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,对其进行初始化并创建一些记录。例如,考虑以下包含User
和Post
模型的 Prisma schema: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 集成以填充数据库的非穷尽工具列表: