スキーマのプロトタイプ作成
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".警告これにより、すべてのデータが失われます。
npx prisma migrate reset
-
Prisma Migrateは、既存のマイグレーション履歴をリプレイし、スキーマ変更に基づいて新しいマイグレーションを生成し、それらの変更をデータベースに適用します。
migrate dev
を使用する際、スキーマ変更によりシードスクリプトが動作しなくなる場合、--skip-seed
フラグを使用してシードスクリプトを無視できます。
この時点で、プロトタイプ作成の最終結果はマイグレーションとして保持され、他の環境(テスト、本番、またはチームの他のメンバー)にプッシュすることができます。