メインコンテンツにスキップ

マイグレーションのカスタマイズ

警告

このガイドはMongoDBには適用されません
MongoDBの場合、migrate devの代わりにdb pushが使用されます (MongoDB参照)。

場合によっては、マイグレーションファイルを適用する前に編集する必要があります。例えば、データ損失なしに1対1リレーションの方向を変更する(外部キーを一方から他方へ移動する)には、マイグレーションの一部としてデータを移動する必要があります。このSQLはデフォルトのマイグレーションには含まれていないため、手動で記述する必要があります。

このガイドでは、マイグレーションファイルを編集する方法と、それを実行したい場合のいくつかの使用例を説明します。

マイグレーションファイルの編集方法

マイグレーションファイルを適用する前に編集するには、一般的な手順は以下の通りです。

  1. カスタムSQLを必要とするスキーマ変更を行います(例:既存のデータを保持するため)

  2. 以下を使用してドラフトマイグレーションを作成します

    npx prisma migrate dev --create-only
  3. 生成されたSQLファイルを変更します。

  4. 以下を実行して、変更されたSQLを適用します

    npx prisma migrate dev

例: フィールド名の変更

デフォルトでは、スキーマ内のフィールド名を変更すると、以下のマイグレーションが生成されます。

  • 新しいカラムをCREATEする(例: fullname
  • 既存のカラム(例: name)とそのカラムのデータをDROPする

本番環境でマイグレーションを実行する際にデータ損失を避けて実際にフィールドをリネームするには、生成されたマイグレーション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を編集して、テーブルを削除して再作成するのではなく、名前を変更します。

例: ダウンタイムなしでスキーマを進化させるための展開・縮小パターンを使用する

既存のフィールドにスキーマ変更を加えること(例:フィールド名の変更)は、ダウンタイムにつながる可能性があります。これは、既存のフィールドを変更するマイグレーションを適用してから、変更されたフィールドを使用する新しいバージョンのアプリケーションコードをデプロイするまでの期間に発生します。

フィールドを変更するために必要な手順を一連の段階的なステップに分割することで、ダウンタイムを防ぐことができます。このパターンは展開・縮小パターンとして知られています。

このパターンには、データベースにアクセスするアプリケーションコードと、変更しようとしているデータベーススキーマという2つのコンポーネントが含まれます。

展開・縮小パターンでは、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

このアプローチを使用することで、アプリケーションコードで使用されている既存のフィールドを変更する際に発生しがちな潜在的なダウンタイムを回避し、マイグレーションの適用と更新されたアプリケーションコードのデプロイに必要な調整の量を減らすことができます。

このパターンは、データがあり、アプリケーションコードで使用されているカラムに対する変更を伴うあらゆる状況に適用可能であることに注意してください。例としては、2つのフィールドを1つに結合したり、1:nリレーションをm:nリレーションに変換したりすることが含まれます。

詳細については、データガイド記事の展開・縮小パターンを確認してください。

例: 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
© . All rights reserved.