数据迁移
Prisma ORM 尚未原生支持数据迁移,但您可以使用扩展和收缩模式来迁移您的数据。例如,从一列迁移到另一列。
本指南介绍了如何使用 Prisma ORM 和扩展和收缩模式来
- 扩展您的模式以添加新列
- 创建和运行数据迁移
- 收缩您的模式以删除旧列
步骤概述
本教程将引导您完成以下步骤
- 扩展您的模式以添加新列
- 创建并运行数据迁移文件
- 收缩您的模式以删除旧列
它还做出以下假设
- 生产数据库可以从开发机器访问
prisma migrate dev
仅针对开发数据库运行- 扩展和收缩步骤在单独的分支中处理
对于本指南,您将通过用 status
枚举替换 published
布尔字段来修改以下模式
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
}
扩展您的模式以添加新列
从您的 main
分支检出到一个新分支
git checkout -b create-status-field
对您的 Prisma 模式进行以下更新
- 创建一个
Status
枚举,包含以下值:Unknown
、Draft
、InReview
和Published
- 向
Post
模型添加一个status
列 - 将
published
字段标记为可选
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean? @default(false)
status Status
}
enum Status {
Unknown
Draft
InProgress
InReview
Published
}
创建一个新的迁移以将 Prisma 模式与数据库模式同步
npx prisma migrate dev --name add-status-column
Prisma Migrate 将向您发出以下警告,因为添加到数据库的字段是不可空的,并且数据库包含需要默认值的数据。
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "data-migration", schema "public" at "localhost:5401"
Error:
⚠️ We found changes that cannot be executed:
• Step 1 Added the required column `status` to the `Post` table without a default value. There are 4 rows in this table, it is not possible to execute this step.
You can use prisma migrate dev --create-only to create the migration file, and manually modify it to address the underlying issue(s).
Then run prisma migrate dev to apply it and verify it works.
退出迁移步骤并通过添加 @default()
属性函数为 status
字段添加默认值来更新模式。
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean? @default(false)
status Status @default(Unknown)
}
enum Status {
Unknown
Draft
InProgress
InReview
Published
}
使用以下命令生成并执行迁移
npx prisma migrate dev --name add-default
创建并运行数据迁移文件
创建数据迁移文件
在上一步骤中生成的迁移文件夹内,创建一个名为 data-migration.ts
的文件。此文件将包含一个数据迁移,该迁移将使用 Prisma Client 实现。
添加以下代码以将数据从 published
字段迁移到您刚刚创建的文件中的 status
字段
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
await prisma.$transaction(async (tx) => {
const posts = await tx.post.findMany()
for (const post of posts) {
await tx.post.update({
where: { id: post.id },
data: {
status: post.published ? 'Published' : 'Unknown',
},
})
}
})
}
main()
.catch(async (e) => {
console.error(e)
process.exit(1)
})
.finally(async () => await prisma.$disconnect())
数据迁移包装在事务中,以确保查询回滚,从而允许您迭代数据迁移文件
后续步骤
- 将您的更改推送到远程源并创建一个新的拉取请求。
- 如果您对更改感到满意,请将更改合并到您的
main
分支。
要将更改应用于您的生产数据库,请将 prisma migrate deploy
作为 CI 中的部署/构建步骤的一部分添加
运行数据迁移
使用脚本更新 package.json
文件以执行数据迁移文件。请务必使用您的迁移文件名更新 20230417131956_add-status-column
。
"scripts": {
"dev": "tsx ./script.ts",
"data-migration:add-status-column": "tsx ./prisma/migrations/20230417131956_add-status-column/data-migration.ts"
},
后续步骤
- 将您的更改推送到远程源并创建一个新的拉取请求。
- 如果您对更改感到满意,请将更改合并到您的“main”分支。
要将更改应用于您的生产数据库,请将 prisma migrate deploy
作为 CI 中的部署/构建步骤的一部分添加。
运行数据迁移
使用您的生产数据库的 URL 更新 DATABASE_URL
环境变量。运行数据迁移脚本
npm run data-migration:add-status-column
收缩您的模式以删除旧列
在您的开发机器上检出到一个单独的分支
git checkout -b drop-published-column
从您的模式中删除 published
字段并生成一个新的迁移
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean? @default(false)
status Status @default(Unknown)
}
enum Status {
Draft
InProgress
InReview
Published
}
生成一个新的迁移
npx prisma migrate dev --name drop-published-column
后续步骤
- 将您的更改推送到远程源并创建一个新的拉取请求。
- 如果您对更改感到满意,请将更改合并到您的
main
分支。
要将更改应用于您的生产数据库,请将 prisma migrate deploy
作为 CI 中的部署/构建步骤的一部分添加
npx prisma migrate deploy
您已成功
- 将数据从
published
列迁移到status
列 - 从您的模式中删除了
published
列