SQLの中間テーブルをPrismaの多対多リレーションに変換する
複合主キーを持つSQLの中間テーブルがPrismaの暗黙的または明示的な多対多リレーションにどのように変換されるかを学びます。両方のパターンとそれぞれの選択基準を解説します。
Relations
詳細な説明
多対多リレーション
SQLは中間(結合)テーブルで2つの外部キーを持つことで多対多リレーションシップをモデル化します。Prismaは暗黙的な多対多(中間modelなし)と明示的な多対多(中間modelあり)の両方をサポートしています。
SQLの例
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE TABLE tags (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE article_tags (
article_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
PRIMARY KEY (article_id, tag_id),
FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
);
暗黙的な多対多(シンプルな中間テーブル)
model Article {
id Int @id @default(autoincrement())
title String
tags Tag[]
@@map("articles")
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
articles Article[]
@@map("tags")
}
Prismaが中間テーブルを自動管理します。コンバーターは、中間テーブルに2つの外部キーカラムと複合主キーのみがあり、追加データカラムがない場合にこのパターンを使用します。
明示的な多対多(追加データ付き中間テーブル)
CREATE TABLE enrollments (
student_id INTEGER NOT NULL,
course_id INTEGER NOT NULL,
enrolled_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
grade CHAR(2),
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
model Student {
id Int @id @default(autoincrement())
enrollments Enrollment[]
@@map("students")
}
model Course {
id Int @id @default(autoincrement())
enrollments Enrollment[]
@@map("courses")
}
model Enrollment {
studentId Int @map("student_id")
courseId Int @map("course_id")
enrolledAt DateTime @default(now()) @map("enrolled_at")
grade String? @db.Char(2)
student Student @relation(fields: [studentId], references: [id])
course Course @relation(fields: [courseId], references: [id])
@@id([studentId, courseId])
@@map("enrollments")
}
暗黙的 vs 明示的の選択
| 基準 | 暗黙的 | 明示的 |
|---|---|---|
| 中間テーブルにFKカラムのみ | はい | いいえ |
| リレーションに追加フィールド | 不可 | 対応 |
| Prismaが中間テーブルを管理 | 自動的に | 自分で管理 |
| 中間テーブルを直接クエリ | 不可 | はい |
コンバーターの検出ロジック
- テーブルが正確に2つの外部キーカラムで複合PKを構成:暗黙的候補
- テーブルに追加の非FKカラム(タイムスタンプ、メタデータ)がある場合:明示的リレーション
- いずれかのFKが同じテーブルを参照する場合(自己参照M:N):常に明示的
マイグレーションの注意
SQLからPrismaの暗黙的M:Nに変換する場合、Prismaは中間テーブルが_ArticleToTag(アルファベット順、アンダースコアプレフィックス)という名前であることを期待します。コンバーターはリネームを処理するか、マイグレーションステップを生成します。
ユースケース
シンプルなタグ割り当て用の中間テーブルと、追加メタデータ付きの受講登録テーブルの両方がある場合に、コンバーターが中間テーブルの構造に基づいてPrismaの暗黙的多対多または明示的中間modelのどちらを使用するかを判断します。