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

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を削除し、ターゲットスキーマに新しいモデルまたは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を参照してください。