資料播種
本指南介紹瞭如何使用 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 resetCLI 命令。 - 在使用
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.tw/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 seedCLI 命令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.tw/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 seedCLI 命令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 整合到開發工作流中以播種資料庫的其他工具的非詳盡列表: