跳至主要内容

自定义迁移

警告

本指南**不适用于 MongoDB**。
对于 MongoDB,使用 db push 而不是 migrate dev

在某些情况下,您需要在应用迁移文件之前对其进行编辑。例如,要更改 1:1 关系的方向(将外键从一侧移到另一侧)而不会丢失数据,您需要将数据作为迁移的一部分移动 - 此 SQL 不是默认迁移的一部分,必须手动编写。

本指南说明如何编辑迁移文件并提供一些您可能希望执行此操作的用例示例。

如何编辑迁移文件

在应用迁移文件之前对其进行编辑,一般步骤如下

  1. 进行需要自定义 SQL 的模式更改(例如,保留现有数据)

  2. 使用以下命令创建草稿迁移

    npx prisma migrate dev --create-only
  3. 修改生成的 SQL 文件。

  4. 通过运行以下命令应用修改后的 SQL

    npx prisma migrate dev

示例:重命名字段

默认情况下,在模式中重命名字段会导致迁移

  • CREATE 新列(例如,fullname
  • DROP 现有列(例如,name)以及该列中的数据

为了实际**重命名**字段并在生产环境中运行迁移时避免数据丢失,您需要在将其应用于数据库之前修改生成的迁移 SQL。考虑以下模式片段 - biograpy 字段拼写错误。

model Profile {
id Int @id @default(autoincrement())
biograpy String
userId Int @unique
user User @relation(fields: [userId], references: [id])
}

要将 biograpy 字段重命名为 biography

  1. 在模式中重命名字段

    model Profile {
    id Int @id @default(autoincrement())
    biograpy String
    biography String
    userId Int @unique
    user User @relation(fields: [userId], references: [id])
    }
  2. 运行以下命令以创建**草稿迁移**,您可以在将其应用于数据库之前对其进行编辑

    npx prisma migrate dev --name rename-migration --create-only
  3. 编辑草稿迁移,如所示,将 DROP / DELETE 更改为单个 RENAME COLUMN

    ./prisma/migrations/20210308092620_rename_migration/migration.sql
    ALTER TABLE "Profile" DROP COLUMN "biograpy",
    ADD COLUMN "biography" TEXT NOT NULL;
  4. 保存并应用迁移

    npx prisma migrate dev

您可以使用相同的技术重命名model - 编辑生成的 SQL 以重命名表,而不是删除并重新创建它。

示例:使用扩展和收缩模式在不中断服务的情况下改进模式

对现有字段进行模式更改(例如,重命名字段)可能会导致停机时间。它发生在应用修改现有字段的迁移与部署使用修改字段的新版本应用程序代码之间的时间范围内。

您可以通过将更改字段所需的步骤分解为一系列旨在逐步引入更改的离散步骤来防止停机。此模式称为扩展和收缩模式

该模式涉及两个组件:访问数据库的应用程序代码和您打算更改的数据库模式。

使用扩展和收缩模式,使用 Prisma 重命名字段 biobiography 将如下所示

  1. 将新的 biography 字段添加到您的 Prisma 模式并创建迁移

    model Profile {
    id Int @id @default(autoincrement())
    bio String
    biography String
    userId Int @unique
    user User @relation(fields: [userId], references: [id])
    }
  2. 扩展:更新应用程序代码并写入 biobiography 字段,但继续从 bio 字段读取,并部署代码

  3. 创建一个空迁移并将现有数据从 bio 复制到 biography 字段

    npx prisma migrate dev --name copy_biography --create-only
    prisma/migrations/20210420000000_copy_biography/migration.sql
    UPDATE "Profile" SET biography = bio;
  4. 验证数据库中 biography 字段的完整性

  5. 更新应用程序代码以从新的 biography 字段读取

  6. 更新应用程序代码以停止写入bio 字段

  7. 收缩:从 Prisma 模式中删除 bio,并创建迁移以删除 bio 字段

    model Profile {
    id Int @id @default(autoincrement())
    bio String
    biography String
    userId Int @unique
    user User @relation(fields: [userId], references: [id])
    }
    npx prisma migrate dev --name remove_bio

通过使用这种方法,您可以避免更改应用程序代码中使用的现有字段容易发生的潜在停机时间,并减少应用迁移和部署更新的应用程序代码之间所需的协调量。

请注意,此模式适用于任何涉及对包含数据且正在被应用程序代码使用的列进行更改的情况。示例包括将两个字段合并为一个,或将 1:n 关系转换为 m:n 关系。

要了解更多信息,请查看 Data Guide 文章扩展和收缩模式

示例:更改 1:1 关系的方向

要更改 1:1 关系的方向

  1. 在模式中进行更改

    model User {
    id Int @id @default(autoincrement())
    name String
    posts Post[]
    profile Profile? @relation(fields: [profileId], references: [id])
    profileId Int @unique
    }

    model Profile {
    id Int @id @default(autoincrement())
    biography String
    user User
    }
  2. 运行以下命令以创建**草稿迁移**,您可以在将其应用于数据库之前对其进行编辑

    npx prisma migrate dev --name rename-migration --create-only
    显示CLI结果
    ⚠️  There will be data loss when applying the migration:

    • The migration will add a unique constraint covering the columns `[profileId]` on the table `User`. If there are existing duplicate values, the migration will fail.
  3. 按如下所示编辑草稿迁移


-- DropForeignKey
ALTER TABLE "Profile" DROP CONSTRAINT "Profile_userId_fkey";

-- DropIndex
DROP INDEX "Profile_userId_unique";

-- AlterTable
ALTER TABLE "Profile" DROP COLUMN "userId";

-- AlterTable
ALTER TABLE "User" ADD COLUMN "profileId" INTEGER NOT NULL;

-- CreateIndex
CREATE UNIQUE INDEX "User_profileId_unique" ON "User"("profileId");

-- AddForeignKey
ALTER TABLE "User" ADD FOREIGN KEY ("profileId") REFERENCES "Profile"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  1. 保存并应用迁移

    npx prisma migrate dev