スキーマのプロトタイピング
Prisma CLIには、スキーマをプロトタイピングするための専用コマンドがあります: db push
db push
は、Prisma Migrateと同じエンジンを使用して、Prismaスキーマとデータベーススキーマを同期させます。db push
コマンドは
-
データベースをイントロスペクトし、データベーススキーマをPrismaスキーマの状態を反映させるために必要な変更を推測して実行します。
-
デフォルトでは、変更がデータベーススキーマに適用された後、ジェネレーター(例えばPrisma Client)がトリガーされます。手動で
prisma generate
を呼び出す必要はありません。 -
db push
が、変更がデータ損失につながる可能性があると予測した場合、- エラーをスローします
- それでも変更を加えたい場合は、
--accept-data-loss
オプションが必要です
注記:
db push
は、マイグレーションと対話したり、マイグレーションに依存したりしません。マイグレーションテーブル_prisma_migrations
は作成または更新されず、マイグレーションファイルも生成されません。- PlanetScaleを使用する場合、
migrate
の代わりにdb push
を使用することをお勧めします。詳細については、状況に応じて、ゼロから始める または 既存のプロジェクトに追加する のいずれかの「はじめに」ドキュメントを参照してください。
db push
または Prisma Migrate の選択
db push
は、次の場合にうまく機能します。
- 他の開発者やステージング環境、本番環境などの他の環境に変更をデプロイする必要なく、ローカルでスキーマ設計を**迅速にプロトタイプおよび反復**したい場合。
- 目的の**最終状態**を優先し、その最終状態に到達するために実行される変更や手順を優先しない場合(
db push
によって行われた変更をプレビューする方法はありません)。 - スキーマの変更がデータに与える影響を制御する必要がない場合。スキーマとデータ移行を調整する方法はありません。
db push
が変更によってデータ損失が発生すると予測した場合、--accept-data-loss
オプションを使用してデータ損失を受け入れるか、プロセスを停止するかのいずれかしかありません。変更をカスタマイズする方法はありません。
db push
をこの方法で使用する方法の例については、db push
を使用したスキーマのプロトタイピング を参照してください。
db push
は、次の場合には**推奨されません**。
- データを失うことなく、スキーマの変更を他の環境に複製したい場合。プロトタイピングには
db push
を使用できますが、スキーマの変更をコミットし、他の環境に適用するにはマイグレーションを使用する必要があります。 - スキーマの変更がどのように実行されるかを細かく制御したい場合 - たとえば、列をドロップして新しい列を作成する代わりに、列の名前を変更する など。
- データベーススキーマに対する変更を時間の経過とともに追跡したい場合。
db push
は、これらの変更を追跡できるアーティファクトを作成しません。 - スキーマの変更を可逆的にしたい場合。元の状態に戻すために
db push
を再度使用できますが、データ損失が発生する可能性があります。
Prisma Migrate と db push
を一緒に使用できますか?
はい、開発ワークフローで db push
と Prisma Migrate を一緒に使用する ことができます。たとえば、次のことができます。
- プロジェクトの開始時に
db push
を使用してスキーマをプロトタイプし、最初のドラフトに満足したらマイグレーション履歴を初期化する db push
を使用して既存のスキーマへの変更をプロトタイプし、次にprisma migrate dev
を実行して変更からマイグレーションを生成する(リセットするように求められます)
新しいスキーマのプロトタイピング
次のシナリオでは、db push
を使用して新しいスキーマを空のデータベースと同期させ、そのスキーマを進化させる方法(db push
が変更によってデータ損失が発生することを検出した場合の処理を含む)を示します。
-
スキーマの最初のドラフトを作成する
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
jobTitle String
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
biograpy String // Intentional typo!
userId Int @unique
user User @relation(fields: [userId], references: [id])
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
posts Post[]
@@unique([name])
} -
db push
を使用して、初期スキーマをデータベースにプッシュするnpx prisma db push
-
いくつかのサンプルコンテンツを作成する
const add = await prisma.user.create({
data: {
name: 'Eloise',
jobTitle: 'Programmer',
posts: {
create: {
title: 'How to create a MySQL database',
content: 'Some content',
},
},
},
}) -
加法的な変更を加える - たとえば、新しい必須フィールドを作成する
// ... //
model Post {
id Int @id @default(autoincrement())
title String
description String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
// ... // -
変更をプッシュする
npx prisma db push
デフォルト値を指定しない限り、既存のコンテンツを持つテーブルに必須フィールドを追加できないため、
db push
は失敗します。 -
データベース内の**すべてのデータ**をリセットし、マイグレーションを再適用します。
npx prisma migrate reset
注:Prisma Migrateとは異なり、
db push
はデータを保持するために変更できるマイグレーションを生成しないため、開発環境でのプロトタイピングに最適です。 -
比較的安定した状態になるまで、スキーマを進化させ続けます。
-
マイグレーション履歴を初期化する
npx prisma migrate dev --name initial-state
最初のプロトタイプに到達するために取られた手順は保持されません -
db push
は履歴を生成しません。 -
マイグレーション履歴とPrismaスキーマをソース管理(例:Git)にプッシュします。
この時点で、プロトタイピングの最終ドラフトがマイグレーションに保存され、他の環境(テスト、本番、またはチームの他のメンバー)にプッシュできます。
既存のマイグレーション履歴を使用したプロトタイピング
次のシナリオでは、マイグレーション履歴がすでに存在するPrismaスキーマへの変更をプロトタイプするために db push
を使用する方法を示します。
-
最新のPrismaスキーマとマイグレーション履歴をチェックアウトする
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
jobTitle String
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
biograpy String // Intentional typo!
userId Int @unique
user User @relation(fields: [userId], references: [id])
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
posts Post[]
@@unique([name])
} -
新しい機能をプロトタイプします。これには、任意の数のステップが含まれる場合があります。たとえば、次の操作を行う場合があります。
tags String[]
フィールドを作成し、db push
を実行する- フィールドタイプを
tags Tag[]
に変更し、Tag
という名前の新しいモデルを追加してから、db push
を実行する - 気が変わって元の
tags String[]
フィールドを復元し、db push
を呼び出す - データベース内の
tags
フィールドを手動で変更する - たとえば、制約を追加する
いくつかの解決策を試した後、最終的なスキーマの変更は次のようになります
model Post {
id Int @id @default(autoincrement())
title String
description String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
tags String[]
} -
新しい
tags
フィールドを追加するマイグレーションを作成するには、migrate dev
コマンドを実行しますnpx prisma migrate dev --name added-tags
プロトタイピング中に手動および
db push
で行った変更はマイグレーション履歴の一部ではないため、Prisma Migrate はリセットするように求めます√ Drift detected: Your database schema is not in sync with your migration history.
We need to reset the PostgreSQL database "prototyping" at "localhost:5432".warningこれにより、データが完全に失われます。
npx prisma migrate reset
-
Prisma Migrateは、既存のマイグレーション履歴をリプレイし、スキーマの変更に基づいて新しいマイグレーションを生成し、それらの変更をデータベースに適用します。
migrate dev
を使用する際、スキーマの変更によってシードスクリプトが機能しなくなる場合は、--skip-seed
フラグを使用してシードスクリプトを無視できます。
この時点で、プロトタイピングの最終結果がマイグレーションに保存され、他の環境(テスト、本番、またはチームの他のメンバー)にプッシュできます。