数据迁移
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
列