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

複数のデータベーススキーマでPrisma ORMを使用する方法

警告

複数のデータベーススキーマのサポートは現在、PostgreSQL、CockroachDB、およびSQL Serverのコネクタで利用可能です。

多くのデータベースプロバイダは、データベースのテーブルを名前付きのグループに整理することを許可しています。これを使用すると、データモデルの論理構造を理解しやすくなったり、テーブル間の名前の衝突を回避したりできます。

PostgreSQL、CockroachDB、SQL Serverでは、これらのグループはスキーマとして知られています。Prisma ORM自身のスキーマと区別するために、これらをデータベーススキーマと呼びます。

このガイドでは、以下の方法について説明します。

  • 複数のデータベーススキーマをPrismaスキーマに含める
  • Prisma Migrateとdb pushを使用してスキーマの変更をデータベースに適用する
  • 複数のデータベーススキーマを持つ既存のデータベースをイントロスペクトする
  • Prisma Clientで複数のデータベーススキーマをまたいでクエリを実行する

multiSchemaプレビュー機能を有効にする方法

マルチスキーマサポートは現在プレビュー中です。multiSchemaプレビュー機能を有効にするには、PrismaスキーマのgeneratorブロックにあるpreviewFeaturesフィールドにmultiSchemaフィーチャーフラグを追加します。

schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["multiSchema"]
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

複数のデータベーススキーマをPrismaスキーマに含める方法

Prismaスキーマファイルで複数のデータベーススキーマを使用するには、datasourceブロックのschemasフィールドに、データベーススキーマの名前を配列で追加します。以下の例では、"base"スキーマと"transactional"スキーマを追加しています。

schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["multiSchema"]
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
schemas = ["base", "transactional"]
}

接続文字列を変更する必要はありません。接続文字列のschema値は、Prisma Clientが接続し、生クエリに使用するデフォルトのデータベーススキーマです。その他のすべてのPrisma Clientクエリは、クエリ対象のモデルまたはenumのスキーマを使用します。

モデルまたはenumが特定のデータベーススキーマに属することを指定するには、@@schema属性をデータベーススキーマの名前をパラメータとして追加します。以下の例では、Userモデルは"base"スキーマの一部であり、OrderモデルとSize enumは"transactional"スキーマの一部です。

schema.prisma
model User {
id Int @id
orders Order[]

@@schema("base")
}

model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int

@@schema("transactional")
}

enum Size {
Small
Medium
Large

@@schema("transactional")
}

異なるデータベーススキーマ内の同名テーブル

異なるデータベーススキーマに同名のテーブルがある場合、Prismaスキーマでテーブル名を一意のモデル名にマッピングする必要があります。これにより、Prisma Clientでモデルをクエリする際の名前の衝突を回避できます。

例えば、baseデータベーススキーマのconfigテーブルが、usersデータベーススキーマのconfigテーブルと同じ名前である状況を考えてみましょう。名前の衝突を避けるには、Prismaスキーマのモデルに一意の名前(BaseConfigUserConfig)を付け、@@map属性を使用して各モデルを対応するテーブル名にマッピングします。

schema.prisma
model BaseConfig {
id Int @id

@@map("config")
@@schema("base")
}

model UserConfig {
id Int @id

@@map("config")
@@schema("users")
}

Prisma Migrateとdb pushでスキーマ変更を適用する方法

Prisma Migrateまたはdb pushを使用して、複数のデータベーススキーマを持つPrismaスキーマに変更を適用できます。

例として、上記のブログ投稿モデルのbaseスキーマにProfileモデルを追加します。

schema.prisma
model User {
id Int @id
orders Order[]
profile Profile?

@@schema("base")
}

model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique

@@schema("base")
}

model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int

@@schema("transactional")
}

enum Size {
Small
Medium
Large

@@schema("transactional")
}

その後、このスキーマ変更をデータベースに適用できます。例えば、migrate devを使用してスキーマ変更をマイグレーションとして作成し、適用できます。

npx prisma migrate dev --name add_profile

モデルまたはenumをあるスキーマから別のスキーマに移動した場合、Prisma ORMはソーススキーマからモデルまたはenumを削除し、ターゲットスキーマに新しいものを作成することに注意してください。

複数のデータベーススキーマを持つ既存のデータベースをイントロスペクトする方法

db pullを使用することで、複数のデータベーススキーマを持つ既存のデータベースを、単一のデータベーススキーマを持つデータベースと同じ方法でイントロスペクトできます。

npx prisma db pull

これにより、Prismaスキーマがデータベースの現在の状態と一致するように更新されます。

異なるデータベーススキーマに同名のテーブルがある場合、Prisma ORMは衝突を指摘する検証エラーを表示します。これを修正するには、イントロスペクトされたモデルを@map属性でリネームしてください。

Prisma Clientで複数のデータベーススキーマをまたいでクエリを実行する方法

Prisma Clientのクエリ構文を変更することなく、複数のデータベーススキーマ内のモデルをクエリできます。例えば、以下のクエリは上記のPrismaスキーマを使用して、特定のユーザーのすべての注文を検索します。

const orders = await prisma.order.findMany({
where: {
user: {
id: 1,
},
},
})

multiSchemaプレビュー機能の詳細

multiSchemaプレビュー機能の今後の計画について詳しく知りたい場合、またはフィードバックを提供したい場合は、弊社のGithub Issueを参照してください。

© . All rights reserved.