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

スキーマのプロトタイピング

Prisma CLIには、スキーマをプロトタイピングするための専用コマンドがあります: db push

db push は、Prisma Migrateと同じエンジンを使用して、Prismaスキーマとデータベーススキーマを同期させます。db push コマンドは

  1. データベースをイントロスペクトし、データベーススキーマをPrismaスキーマの状態を反映させるために必要な変更を推測して実行します。

  2. デフォルトでは、変更がデータベーススキーマに適用された後、ジェネレーター(例えばPrisma Client)がトリガーされます。手動で prisma generate を呼び出す必要はありません。

  3. 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 が変更によってデータ損失が発生することを検出した場合の処理を含む)を示します。

  1. スキーマの最初のドラフトを作成する

    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])
    }
  2. db push を使用して、初期スキーマをデータベースにプッシュする

    npx prisma db push
  3. いくつかのサンプルコンテンツを作成する

    const add = await prisma.user.create({
    data: {
    name: 'Eloise',
    jobTitle: 'Programmer',
    posts: {
    create: {
    title: 'How to create a MySQL database',
    content: 'Some content',
    },
    },
    },
    })
  4. 加法的な変更を加える - たとえば、新しい必須フィールドを作成する

    // ... //

    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[]
    }

    // ... //
  5. 変更をプッシュする

    npx prisma db push

    デフォルト値を指定しない限り、既存のコンテンツを持つテーブルに必須フィールドを追加できないため、db push は失敗します。

  6. データベース内の**すべてのデータ**をリセットし、マイグレーションを再適用します。

    npx prisma migrate reset

    :Prisma Migrateとは異なり、db push はデータを保持するために変更できるマイグレーションを生成しないため、開発環境でのプロトタイピングに最適です。

  7. 比較的安定した状態になるまで、スキーマを進化させ続けます。

  8. マイグレーション履歴を初期化する

    npx prisma migrate dev --name initial-state

    最初のプロトタイプに到達するために取られた手順は保持されません - db push は履歴を生成しません。

  9. マイグレーション履歴とPrismaスキーマをソース管理(例:Git)にプッシュします。

この時点で、プロトタイピングの最終ドラフトがマイグレーションに保存され、他の環境(テスト、本番、またはチームの他のメンバー)にプッシュできます。

既存のマイグレーション履歴を使用したプロトタイピング

次のシナリオでは、マイグレーション履歴がすでに存在するPrismaスキーマへの変更をプロトタイプするために db push を使用する方法を示します。

  1. 最新の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])
    }
  2. 新しい機能をプロトタイプします。これには、任意の数のステップが含まれる場合があります。たとえば、次の操作を行う場合があります。

    • 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[]
    }
  3. 新しい 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
  4. Prisma Migrateは、既存のマイグレーション履歴をリプレイし、スキーマの変更に基づいて新しいマイグレーションを生成し、それらの変更をデータベースに適用します。

ヒント

migrate dev を使用する際、スキーマの変更によってシードスクリプトが機能しなくなる場合は、--skip-seed フラグを使用してシードスクリプトを無視できます。

この時点で、プロトタイピングの最終結果がマイグレーションに保存され、他の環境(テスト、本番、またはチームの他のメンバー)にプッシュできます。