移行のカスタマイズ
このガイドはMongoDBには適用されません。migrate dev
の代わりに、<コード>db pushがMongoDBに使用されます。
シナリオによっては、移行ファイル を適用する前に編集する必要があります。たとえば、データ損失なしに1対1のリレーションの方向を変更する(外部キーを一方の側から他方の側に移動する)には、移行の一部としてデータを移動する必要があります - このSQLはデフォルトの移行には含まれておらず、手動で記述する必要があります。
このガイドでは、移行ファイルを編集する方法と、これを行う可能性のあるユースケースの例をいくつか説明します。
移行ファイルを編集する方法
移行ファイルを適用する前に編集するための一般的な手順は次のとおりです。
-
カスタムSQLを必要とするスキーマ変更を行う(既存のデータを保持するなど)
-
以下を使用してドラフト移行を作成する
npx prisma migrate dev --create-only
-
生成されたSQLファイルを変更します。
-
変更した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
に名前変更するには
-
スキーマ内のフィールドの名前を変更する
model Profile {
id Int @id @default(autoincrement())
biograpy String
biography String
userId Int @unique
user User @relation(fields: [userId], references: [id])
} -
次のコマンドを実行して、データベースに適用する前に編集できるドラフト移行を作成します。
npx prisma migrate dev --name rename-migration --create-only
-
示すようにドラフト移行を編集し、
DROP
/DELETE
を単一のRENAME COLUMN
に変更します。- 前
- 後
./prisma/migrations/20210308092620_rename_migration/migration.sqlALTER TABLE "Profile" DROP COLUMN "biograpy",
ADD COLUMN "biography" TEXT NOT NULL;./prisma/migrations/20210308092620_rename_migration/migration.sqlALTER TABLE "Profile"
RENAME COLUMN "biograpy" TO "biography"SQL Serverの場合、
ALTER TABLE RENAME COLUMN
の代わりにストアドプロシージャsp_rename
を使用する必要があります。./prisma/migrations/20210308092620_rename_migration/migration.sqlEXEC sp_rename 'dbo.Profile.biograpy', 'biography', 'COLUMN';
-
移行を保存して適用する
npx prisma migrate dev
同じ手法を使用してmodel
の名前を変更できます。生成されたSQLを編集して、テーブルをドロップして再作成するのではなく名前を変更します。
例:ダウンタイムなしでスキーマを進化させるために拡張および縮小パターンを使用する
既存のフィールドへのスキーマ変更(フィールドの名前変更など)は、ダウンタイムにつながる可能性があります。これは、既存のフィールドを変更する移行を適用してから、変更されたフィールドを使用するアプリケーションコードの新しいバージョンをデプロイするまでの時間枠で発生します。
フィールドを変更するために必要な手順を、変更を段階的に導入するように設計された一連の個別の手順に分解することで、ダウンタイムを防ぐことができます。このパターンは、拡張および縮小パターンとして知られています。
このパターンには、データベースにアクセスするアプリケーションコードと、変更する予定のデータベーススキーマの2つのコンポーネントが含まれます。
拡張および縮小パターンを使用すると、フィールドbio
の名前をbiography
に変更すると、Prismaでは次のようになります。
-
新しい
biography
フィールドをPrismaスキーマに追加し、移行を作成します。model Profile {
id Int @id @default(autoincrement())
bio String
biography String
userId Int @unique
user User @relation(fields: [userId], references: [id])
} -
拡張:アプリケーションコードを更新し、
bio
フィールドとbiography
フィールドの両方に書き込みますが、bio
フィールドから読み取り続け、コードをデプロイします。 -
空の移行を作成し、既存のデータを
bio
フィールドからbiography
フィールドにコピーします。npx prisma migrate dev --name copy_biography --create-only
prisma/migrations/20210420000000_copy_biography/migration.sqlUPDATE "Profile" SET biography = bio;
-
データベース内の
biography
フィールドの整合性を検証します。 -
新しい
biography
フィールドから読み取るようにアプリケーションコードを更新します。 -
bio
フィールドへの書き込みを停止するようにアプリケーションコードを更新します。 -
縮小: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のリレーションの方向を変更するには
-
スキーマで変更を加える
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
} -
次のコマンドを実行して、データベースに適用する前に編集できるドラフト移行を作成します。
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. -
示すようにドラフト移行を編集する
- 前
- 後
-- 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;
-- DropForeignKey
ALTER TABLE "Profile" DROP CONSTRAINT "Profile_userId_fkey";
-- DropIndex
DROP INDEX "Profile_userId_unique";
-- AlterTable
ALTER TABLE "User" ADD COLUMN "profileId" INTEGER;
UPDATE "User"
SET "profileId" = "Profile".id
FROM "Profile"
WHERE "User".id = "Profile"."userId";
ALTER TABLE "User" ALTER COLUMN "profileId" SET NOT NULL;
-- AlterTable
ALTER TABLE "Profile" DROP COLUMN "userId";
-- 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;
-
移行を保存して適用する
npx prisma migrate dev