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

移行のカスタマイズ

警告

このガイドはMongoDBには適用されません
migrate devの代わりに、<コード>db pushMongoDBに使用されます。

シナリオによっては、移行ファイル を適用する前に編集する必要があります。たとえば、データ損失なしに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つのコンポーネントが含まれます。

拡張および縮小パターンを使用すると、フィールドbioの名前をbiographyに変更すると、Prismaでは次のようになります。

  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. 拡張:アプリケーションコードを更新し、bioフィールドとbiographyフィールドの両方に書き込みますが、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