跳至主要内容

数据迁移

Prisma ORM 尚未原生支持数据迁移,但您可以使用扩展和收缩模式来迁移您的数据。例如,从一列迁移到另一列。

本指南介绍了如何使用 Prisma ORM 和扩展和收缩模式来

  • 扩展您的模式以添加新列
  • 创建和运行数据迁移
  • 收缩您的模式以删除旧列

步骤概述

本教程将引导您完成以下步骤

  1. 扩展您的模式以添加新列
  2. 创建并运行数据迁移文件
  3. 收缩您的模式以删除旧列

它还做出以下假设

  • 生产数据库可以从开发机器访问
  • prisma migrate dev 仅针对开发数据库运行
  • 扩展和收缩步骤在单独的分支中处理

对于本指南,您将通过用 status 枚举替换 published 布尔字段来修改以下模式

prisma/schema.prisma
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 枚举,包含以下值:UnknownDraftInReviewPublished
  • Post 模型添加一个 status
  • published 字段标记为可选
prisma/schema.prisma
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 字段添加默认值来更新模式。

prisma/schema.prisma
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 字段

prisma/migrations/20230417131956_add-status-column/data-migration.ts
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())

数据迁移包装在事务中,以确保查询回滚,从而允许您迭代数据迁移文件

后续步骤

  1. 将您的更改推送到远程源并创建一个新的拉取请求。
  2. 如果您对更改感到满意,请将更改合并到您的 main 分支。

要将更改应用于您的生产数据库,请将 prisma migrate deploy 作为 CI 中的部署/构建步骤的一部分添加

运行数据迁移

使用脚本更新 package.json 文件以执行数据迁移文件。请务必使用您的迁移文件名更新 20230417131956_add-status-column

package.json
"scripts": {
"dev": "tsx ./script.ts",
"data-migration:add-status-column": "tsx ./prisma/migrations/20230417131956_add-status-column/data-migration.ts"
},

后续步骤

  1. 将您的更改推送到远程源并创建一个新的拉取请求。
  2. 如果您对更改感到满意,请将更改合并到您的“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

后续步骤

  1. 将您的更改推送到远程源并创建一个新的拉取请求。
  2. 如果您对更改感到满意,请将更改合并到您的 main 分支。

要将更改应用于您的生产数据库,请将 prisma migrate deploy 作为 CI 中的部署/构建步骤的一部分添加

npx prisma migrate deploy

您已成功

  • 将数据从 published 列迁移到 status
  • 从您的模式中删除了 published