Kento
Prismaテーブル作成とリレーション
2026年08月12日
要約を生成中...
はじめに
Prismaを使ってテーブル作成をしたので、自分メモ用に残しておきます。 ドキュメントや記事を参考にしています。 間違いなどのコメントも大歓迎! むしろ教えて欲しいです笑
概要
背景
DB設計
テーブル作成
リレーション
おわり
背景
簡易的なWEBアプリを作成しようと思い、今回Prismaを採用しました。 エラーログナレッジ管理アプリ。 シンプルに、エラーログをメモで残すように管理するアプリです! ユーザーが、開発中に遭遇したエラーをログとして、以下の内容を入力して投稿する。
タイトル
エラーログの内容
ステータス(解決済み?未解決?)
使用技術をタグで付与
開発環境(OS, フレームワークバージョン、フレームワーク)
エラーの原因・解決方法
DB設計
やりたいこと
今回のアプリでのリレーションを整理。
1人のユーザーが1件または複数のエラーログを投稿・編集できる(1対多)
1件のErrorLogの投稿者は、1人のUserである。(1対多)
①ユーザー
├── ①エラーログ
├── ②エラーログ
├── ③エラーログ
①エラーログ
├── ①ユーザー
②エラーログ
├── ②ユーザー
1つのTagが複数のエラーログに付与できる。(多対多)
1件のエラーログに、複数のタグを付与できる。(多対多)
①タグ(React)
├── ①エラーログ
├── ②エラーログ
├── ③エラーログ
①エラーログ
├── ①タグ(React)
├── ②タグ(Next.js)
├── ③タグ(TypeScript)
多対多は、お互い関連するテーブルのidを複数お互い持っていること。 多対多の問題点として、DBテーブルの一つのカラムには、一つの情報しか入れられない。

これを解消するために、中間テーブルを設ける必要がある。 中間テーブルにTagとErrorLogのそれぞれの外部キーを持たせることで、「どのErrorLogにどのTagがついているのか」という関係を保存するため。
テーブル作成
Prismaでは、schema.prismaというファイルで、テーブル作成をします。
// schema.prisma
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
userName String @db.VarChar(255)
profileIcon String @db.Text
xUrl String @db.Text
instagramUrl String @db.Text
githubUrl String @db.Text
email String @db.VarChar(255)
password_hash String @db.VarChar(255)
errorLog ErrorLog[]
}
enum ResolutionStatus {
RESOLVED
UNRESOLVED
}
model ErrorLog {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
title String @db.VarChar(255)
status ResolutionStatus @default(UNRESOLVED)
os String @db.VarChar(255)
framework_version String @db.VarChar(255)
framework String @db.VarChar(255)
solution String? @db.Text
cause String @db.Text
error_message String @db.Text
userId String
user User @relation(fields: [userId], references: [id])
errorLogTag ErrorLogTag[]
}
model Tag {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
tag_name String @db.VarChar(100)
errorLogTag ErrorLogTag[]
}
model ErrorLogTag {
id String @id @default(uuid())
errorLogId String
tagId String
errorlog ErrorLog @relation(fields: [errorLogId], references: [id])
tag Tag @relation(fields: [tagId], references: [id])
@@unique([errorLogId, tagId])
}
generator
作成したテーブル構造をもとに、何かを自動生成するもの
provider
prisma generateコマンド実行時にどのジェネレータを使って、生成するかを指定
output
prisma-clientで生成したファイルの出力先
datasource
Prismaをデータベースを接続するための設定。 postgresqlを指定しています。
Prisma ORM v7からの変更点で、データベースの接続先のurlは、prisma.config.tsで設定する必要がある。
import "dotenv/config";
import { defineConfig } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: process.env.DATABASE_URL,
},
});
モデル定義
Prismaのモデ定義する際は、モデル名は複数形ではなく単数形にするルールがあります。
model Users ❌ → model User ✅
モデルのカラム定義は、左から順番に「カラム名 + データ型 + 属性」で記載していきます。
下のモデルで言うと、カラム名:id, データ型:String, 属性:@id @default(uuid())となります。
model User {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
userName String @db.VarChar(255)
profileIcon String @db.Text
xUrl String @db.Text
instagramUrl String @db.Text
githubUrl String @db.Text
email String @db.VarChar(255)
password_hash String @db.VarChar(255)
errorLog ErrorLog[] // 1 User : 多 ErrorLog
}
データ型や属性については、以下の公式ドキュメントをご覧ください。
https://www.prisma.io/docs/orm/reference/prisma-schema-reference
リレーション
1対多の場合のリレーション定義
1対多のリレーションの場合は、以下の通りに書きます。
1個のモデル: 子モデルの型名に[]を加える。
Userが複数のErrorLog投稿ができるため)多のモデル: 親のidと一致する外部キー用意し、
@relation(fields: [外部キー], references: [親のID])を付与する。

model User {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
userName String @db.VarChar(255)
profileIcon String @default("")
xUrl String @default("")
instagramUrl String @default("")
githubUrl String @default("")
email String @db.VarChar(255)
password_hash String @db.VarChar(255)
errorLog ErrorLog[]
}
enum ResolutionStatus {
RESOLVED
UNRESOLVED
}
model ErrorLog {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
title String @db.VarChar(255)
status ResolutionStatus @default(UNRESOLVED)
os String @db.VarChar(255)
framework_version String @db.VarChar(255)
framework String @db.VarChar(255)
solution String? @db.Text
cause String @db.Text
error_message String @db.Text
userId String
user User @relation(fields: [userId], references: [id])
errorLogTag ErrorLogTag[]
}
中間テーブルの場合のリレーション定義
ErrorLogモデルとTagモデルは、多対多のリレーション(関係)。
1つのTagが複数のエラーログに付与できる。(多対多)
1件のエラーログに、複数のタグを付与できる。(多対多)
なので、中間テーブルを設けて「どのErrorLogにどのTagがついているのか」という関係を保存する。両親のモデル:
中間モデルの型名に [] を加える。(1つの親が複数の中間データを持てるため)中間モデル:
2つの親のidと一致する外部キーをそれぞれ用意し、@relation をそれぞれに付与する。さらに @@unique([外部キー①, 外部キー②]) で複合主キーを設定して重複を防ぐ。Prismaで複合キーを使う場合は、@@uniqueを使う。

model ErrorLog {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
title String @db.VarChar(255)
status ResolutionStatus @default(UNRESOLVED)
os String @db.VarChar(255)
framework_version String @db.VarChar(255)
framework String @db.VarChar(255)
solution String? @db.Text
cause String @db.Text
error_message String @db.Text
userId String
user User @relation(fields: [userId], references: [id])
errorLogTag ErrorLogTag[]
}
model Tag {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
tag_name String @db.VarChar(100)
errorLogTag ErrorLogTag[]
}
model ErrorLogTag {
id String @id @default(uuid())
errorLogId String
tagId String
errorlog ErrorLog @relation(fields: [errorLogId], references: [id])
tag Tag @relation(fields: [tagId], references: [id])
@@unique([errorLogId, tagId])
}
おわり
今回は、Prismaを使ったテーブル作成とリレーションについてメモ程度に残しただけなので、参考になっていただけたら幸いです。


