データベース
テーブルの追加、マイグレーション、アプリからのクエリ方法。
すべてのアプリは単一のPostgresデータベースを共有しています。Prismaはスキーマを管理(マイグレーション生成も含む)し、アプリはランタイムでpgライブラリを使います。ローカルでマイグレーションを実行することはありません — PRとマージ時に自動生成・自動適用されます。
単一のスキーマファイル
すべてのアプリのすべてのテーブルは1つのファイルに入っています:
shared/database/prisma/schema.prisma
あなたのアプリのテーブルは、他のすべてのアプリのテーブルと同じファイルに並びます。所有者が一目でわかるように、アプリ固有のテーブルには必ずアプリ名のsnake_caseプレフィックスを付けてください:
// ============================================
// Meal Planner Tables
// ============================================
model MealPlanner_Recipe {
id String @id @default(cuid())
name String
createdAt DateTime @default(now())
@@map("meal_planner_recipe")
}
@@map(...)が実際のSQLテーブル名で、Prismaモデル名はコード生成時の可読性のためのものです。
詳しい規則は命名規則を参照してください。
マイグレーションワークフロー(ローカル設定不要)
prisma migrate devを叩いたり、.sqlファイルを手で管理することはありません。パイプラインがやってくれます:
- スキーマを編集:
shared/database/prisma/schema.prismaにモデルを追加/変更。 - ドキュメントを更新: shared/schema.mdに所有者、目的、関連を反映。
- フィーチャーブランチにコミット・プッシュし、
mainへのPRを作成。 - CIがマイグレーションを自動生成してPRにコミットバック。
- PR専用のNeon DBブランチが作成され、マイグレーションが適用され、プレビューアプリがそのDBでデプロイされます。
mainへマージすると、Neon mainにマイグレーションが適用され、本番が再デプロイされます。
追加変更を優先しましょう: 既存を修正するのではなく、新しいテーブルやNULL可能カラムを追加します。データマイグレーションが必要なスキーマ変更は開発者のレビューが必要です。
ランタイムでのクエリ
pgをテンプレートのgetDb()ヘルパー(app/_lib/db.ts)経由で使います。必ずパラメータ化クエリ($1, $2, …)を使ってください:
import { getDb } from '@/app/_lib/db';
const db = getDb();
const result = await db.query(
'SELECT * FROM meal_planner_recipe WHERE user_id = $1',
[userId]
);
const recipes = result.rows;import { getDb } from '@/app/_lib/db';
const db = getDb();
const result = await db.query(
'INSERT INTO meal_planner_recipe (name, user_id) VALUES ($1, $2) RETURNING *',
[name, userId]
);
const newRecipe = result.rows[0];文字列連結でSQLを組み立てないでください — SQLインジェクションになります。$1 / $2プレースホルダを使いましょう。
実際にDBに当たる場所
データベースクエリはPRプレビュー環境と本番でのみ動きます — ローカルでは動きません。PRを開くと、パイプラインがマイグレーションを適用した専用Neonブランチを作成し、プレビューデプロイがそこに接続されます。データベースの挙動はそこでテストします。プレビューURLはPRコメントに投稿されます。
うまくいかないとき
PRのマイグレーションステップが失敗(赤いチェック)したときは、トラブルシューティングのデータベースマイグレーションエラーを参照してください。
クイズ
`shared/database/prisma/schema.prisma`に新しいモデルを追加しました。本番データベースに反映させるために次に何をしますか?