jpskill.com
🛠️ 開発・MCP コミュニティ

sqlmodel-expert

SQLModelモデルの作成、リレーション定義、データベース移行設定、N+1問題解決、クエリ最適化など、SQLModelとAlembicを使った高度なデータベース操作やORMパターンに関する課題を支援するSkill。

📜 元の英語説明(参考)

Advanced SQLModel patterns and comprehensive database migrations with Alembic. Use when creating SQLModel models, defining relationships (one-to-many, many-to-many, self-referential), setting up database migrations, optimizing queries, solving N+1 problems, implementing inheritance patterns, working with composite keys, creating indexes, performing data migrations, or troubleshooting Alembic issues. Triggers include "SQLModel", "Alembic migration", "database model", "relationship", "foreign key", "migration", "N+1 query", "query optimization", "database schema", or questions about ORM patterns.

🇯🇵 日本人クリエイター向け解説

一言でいうと

SQLModelモデルの作成、リレーション定義、データベース移行設定、N+1問題解決、クエリ最適化など、SQLModelとAlembicを使った高度なデータベース操作やORMパターンに関する課題を支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o sqlmodel-expert.zip https://jpskill.com/download/23594.zip && unzip -o sqlmodel-expert.zip && rm sqlmodel-expert.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/23594.zip -OutFile "$d\sqlmodel-expert.zip"; Expand-Archive "$d\sqlmodel-expert.zip" -DestinationPath $d -Force; ri "$d\sqlmodel-expert.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して sqlmodel-expert.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → sqlmodel-expert フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
7

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

SQLModel Expert

プロダクションデータベースのための高度なSQLModelパターンと包括的なAlembicマイグレーションです。

クイックスタート

基本モデルの定義

from sqlmodel import Field, SQLModel
from typing import Optional
from datetime import datetime

class Task(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str = Field(index=True)
    description: Optional[str] = None
    completed: bool = Field(default=False)
    created_at: datetime = Field(default_factory=datetime.utcnow)

データベースの初期化

# 提供されているスクリプトを使用
python scripts/init_db.py --url postgresql://user:pass@localhost/db

# または手動で
from sqlmodel import create_engine
engine = create_engine("postgresql://user:pass@localhost/db")
SQLModel.metadata.create_all(engine)

マイグレーションの作成

# 提供されているヘルパースクリプトを使用
./scripts/migrate.sh create "add user table"

# またはAlembicを直接使用
alembic revision --autogenerate -m "add user table"
alembic upgrade head

主要トピック

1. 高度なモデルパターン

参照: references/advanced-models.md

  • リレーションシップ: 1対多、多対多、自己参照
  • 継承: 単一テーブル、結合テーブル、ポリモーフィズム
  • バリデーション: Pydanticバリデーター、カスタム制約
  • Mixin: タイムスタンプ、ソフトデリート、再利用可能なパターン
  • フィールド型: Enum、JSON、配列、カスタム型
  • インデックス: 単一、複合、部分インデックス
  • 制約: ユニーク、チェック、外部キーカスケード

2. 包括的なマイグレーション

参照: references/migrations.md

  • Alembicセットアップ: 設定、SQLModel用のenv.py
  • マイグレーションの作成: 自動生成 vs 手動
  • スキーマ変更: カラムの追加/削除、名前変更、型の変更
  • データマイグレーション: 複雑なデータ変換
  • プロダクションワークフロー: ゼロダウンタイムマイグレーション
  • ロールバック戦略: 安全なダウングレードパターン
  • トラブルシューティング: よくある問題と解決策

3. クエリ最適化

参照: references/queries-optimization.md

  • N+1問題: イーガーローディングによる解決策
  • クエリパターン: JOIN、集計、サブクエリ
  • パフォーマンス: インデックス、バッチ操作、プロファイリング
  • 高度なクエリ: ウィンドウ関数、CTE
  • バルク操作: 大規模な挿入、更新、削除
  • テスト: クエリカウント、explain analyze

一般的なパターン

1対多のリレーションシップ

from typing import List
from sqlmodel import Field, Relationship, SQLModel

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str

    # 1つのチームは多くのヒーローを持つ
    heroes: List["Hero"] = Relationship(back_populates="team")

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    team_id: Optional[int] = Field(foreign_key="team.id")

    # 多くのヒーローは1つのチームに属する
    team: Optional[Team] = Relationship(back_populates="heroes")

リンクテーブルを使用した多対多

class HeroTeamLink(SQLModel, table=True):
    hero_id: int = Field(foreign_key="hero.id", primary_key=True)
    team_id: int = Field(foreign_key="team.id", primary_key=True)
    joined_at: datetime = Field(default_factory=datetime.utcnow)

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    teams: List["Team"] = Relationship(
        back_populates="heroes",
        link_model=HeroTeamLink
    )

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    heroes: List[Hero] = Relationship(
        back_populates="teams",
        link_model=HeroTeamLink
    )

N+1クエリ問題の解決

from sqlalchemy.orm import selectinload

# BAD - N+1クエリ
users = session.exec(select(User)).all()
for user in users:
    posts = user.posts  # それぞれがクエリをトリガーします!

# GOOD - イーガーローディング (合計2クエリ)
statement = select(User).options(selectinload(User.posts))
users = session.exec(statement).all()
for user in users:
    posts = user.posts  # 追加のクエリは発生しません!

マイグレーションの作成

# 1. モデルを変更します
class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    email: str
    phone: str  # 新しいフィールドを追加

# 2. マイグレーションを生成します
# alembic revision --autogenerate -m "add phone to user"

# 3. 生成されたマイグレーションを確認します
def upgrade() -> None:
    op.add_column('user', sa.Column('phone', sa.String(), nullable=True))

def downgrade() -> None:
    op.drop_column('user', 'phone')

# 4. マイグレーションを適用します
# alembic upgrade head

マイグレーションヘルパースクリプト

データベースの初期化

python scripts/init_db.py --url postgresql://user:pass@localhost/db

マイグレーション操作

./scripts/migrate.sh init              # Alembicを初期化
./scripts/migrate.sh create "message"  # マイグレーションを作成
./scripts/migrate.sh upgrade           # マイグレーションを適用
./scripts/migrate.sh downgrade         # 1つロールバック
./scripts/migrate.sh current           # 現在の状況を表示
./scripts/migrate.sh history           # 履歴を表示
./scripts/migrate.sh test              # アップ&ダウンをテスト

モデル例

assets/example-models.py のモデル例をテンプレートとして使用してください。

  • タイムスタンプMixinを持つUserモデル
  • Enumとリレーションシップを持つTaskモデル
  • 多対多を持つTeamモデル
  • リンクテーブルを持つタグシステム
  • 読み取り/書き込み/更新用の個別のモデル

プロジェクトにコピーします。

cp assets/example-models.py your-project/app/models.py

ベストプラクティスチェックリスト

モデル設計

  • [ ] すべてのフィールドに型ヒントを使用する
  • [ ] 読み取り/書き込み/更新モデルを分離する
  • [ ] 共通の機能にMixinを使用する
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

SQLModel Expert

Advanced SQLModel patterns and comprehensive Alembic migrations for production databases.

Quick Start

Define a Basic Model

from sqlmodel import Field, SQLModel
from typing import Optional
from datetime import datetime

class Task(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str = Field(index=True)
    description: Optional[str] = None
    completed: bool = Field(default=False)
    created_at: datetime = Field(default_factory=datetime.utcnow)

Initialize Database

# Using provided script
python scripts/init_db.py --url postgresql://user:pass@localhost/db

# Or manually
from sqlmodel import create_engine
engine = create_engine("postgresql://user:pass@localhost/db")
SQLModel.metadata.create_all(engine)

Create Migration

# Using provided helper script
./scripts/migrate.sh create "add user table"

# Or directly with Alembic
alembic revision --autogenerate -m "add user table"
alembic upgrade head

Core Topics

1. Advanced Model Patterns

See: references/advanced-models.md

  • Relationships: One-to-many, many-to-many, self-referential
  • Inheritance: Single table, joined table, polymorphism
  • Validation: Pydantic validators, custom constraints
  • Mixins: Timestamp, soft delete, reusable patterns
  • Field Types: Enums, JSON, arrays, custom types
  • Indexes: Single, composite, partial indexes
  • Constraints: Unique, check, foreign key cascades

2. Comprehensive Migrations

See: references/migrations.md

  • Alembic Setup: Configuration, env.py for SQLModel
  • Creating Migrations: Autogenerate vs manual
  • Schema Changes: Add/drop columns, rename, change types
  • Data Migrations: Complex data transformations
  • Production Workflow: Zero-downtime migrations
  • Rollback Strategies: Safe downgrade patterns
  • Troubleshooting: Common issues and solutions

3. Query Optimization

See: references/queries-optimization.md

  • N+1 Problem: Solutions with eager loading
  • Query Patterns: Joins, aggregations, subqueries
  • Performance: Indexes, batch operations, profiling
  • Advanced Queries: Window functions, CTEs
  • Bulk Operations: Insert, update, delete at scale
  • Testing: Query counting, explain analyze

Common Patterns

One-to-Many Relationship

from typing import List
from sqlmodel import Field, Relationship, SQLModel

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str

    # One team has many heroes
    heroes: List["Hero"] = Relationship(back_populates="team")

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    team_id: Optional[int] = Field(foreign_key="team.id")

    # Many heroes belong to one team
    team: Optional[Team] = Relationship(back_populates="heroes")

Many-to-Many with Link Table

class HeroTeamLink(SQLModel, table=True):
    hero_id: int = Field(foreign_key="hero.id", primary_key=True)
    team_id: int = Field(foreign_key="team.id", primary_key=True)
    joined_at: datetime = Field(default_factory=datetime.utcnow)

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    teams: List["Team"] = Relationship(
        back_populates="heroes",
        link_model=HeroTeamLink
    )

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    heroes: List[Hero] = Relationship(
        back_populates="teams",
        link_model=HeroTeamLink
    )

Solving N+1 Query Problem

from sqlalchemy.orm import selectinload

# BAD - N+1 queries
users = session.exec(select(User)).all()
for user in users:
    posts = user.posts  # Each triggers a query!

# GOOD - Eager loading (2 queries total)
statement = select(User).options(selectinload(User.posts))
users = session.exec(statement).all()
for user in users:
    posts = user.posts  # No additional query!

Creating a Migration

# 1. Modify your model
class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    email: str
    phone: str  # New field added

# 2. Generate migration
# alembic revision --autogenerate -m "add phone to user"

# 3. Review generated migration
def upgrade() -> None:
    op.add_column('user', sa.Column('phone', sa.String(), nullable=True))

def downgrade() -> None:
    op.drop_column('user', 'phone')

# 4. Apply migration
# alembic upgrade head

Migration Helper Scripts

Initialize Database

python scripts/init_db.py --url postgresql://user:pass@localhost/db

Migration Operations

./scripts/migrate.sh init              # Initialize Alembic
./scripts/migrate.sh create "message"  # Create migration
./scripts/migrate.sh upgrade           # Apply migrations
./scripts/migrate.sh downgrade         # Rollback one
./scripts/migrate.sh current           # Show current
./scripts/migrate.sh history           # Show history
./scripts/migrate.sh test              # Test up & down

Example Models

Use the example models in assets/example-models.py as templates:

  • User model with timestamp mixin
  • Task model with enums and relationships
  • Team model with many-to-many
  • Tag system with link tables
  • Separate read/write/update models

Copy to your project:

cp assets/example-models.py your-project/app/models.py

Best Practices Checklist

Model Design

  • [ ] Use type hints for all fields
  • [ ] Separate read/write/update models
  • [ ] Use mixins for common fields (timestamps, soft delete)
  • [ ] Define indexes on foreign keys and frequently queried columns
  • [ ] Use enums for constrained choices
  • [ ] Implement proper validation with Pydantic validators

Relationships

  • [ ] Use back_populates for bidirectional relationships
  • [ ] Create explicit link tables for many-to-many
  • [ ] Consider cascade delete behavior
  • [ ] Use eager loading to prevent N+1 queries
  • [ ] Index foreign key columns

Migrations

  • [ ] Always review autogenerated migrations
  • [ ] One logical change per migration
  • [ ] Test both upgrade and downgrade
  • [ ] Use descriptive migration names
  • [ ] Never edit applied migrations
  • [ ] Add data migrations when changing schemas
  • [ ] Backup database before production migrations

Query Optimization

  • [ ] Use eager loading (selectinload) for relationships
  • [ ] Select only needed columns
  • [ ] Use indexes for WHERE/ORDER BY columns
  • [ ] Batch operations instead of loops
  • [ ] Profile slow queries
  • [ ] Use connection pooling

Troubleshooting Guide

Migration Issues

Problem: Alembic doesn't detect model changes

# Solution: Ensure models are imported in env.py
from app.models import User, Task, Team  # Import all models
target_metadata = SQLModel.metadata

Problem: Failed migration

# Check current state
alembic current

# Manually fix issue, then stamp
alembic stamp head

# Or downgrade and retry
alembic downgrade -1
alembic upgrade head

Query Performance

Problem: Slow queries

# Enable query logging
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

# Use EXPLAIN ANALYZE
explain = session.exec(text("EXPLAIN ANALYZE SELECT ...")).all()

# Profile queries
# See references/queries-optimization.md for detailed patterns

Problem: N+1 queries

# Use selectinload
statement = select(User).options(selectinload(User.posts))

# Or joinedload
from sqlalchemy.orm import joinedload
statement = select(User).options(joinedload(User.posts))

Production Workflow

Development

  1. Modify SQLModel models
  2. Generate migration: ./scripts/migrate.sh create "description"
  3. Review generated migration file
  4. Test migration: ./scripts/migrate.sh test
  5. Commit migration file

Staging

  1. Deploy application code
  2. Run migrations: alembic upgrade head
  3. Verify data integrity
  4. Test application

Production

  1. Backup database: pg_dump mydb > backup.sql
  2. Deploy in maintenance window
  3. Run migrations: alembic upgrade head
  4. Monitor logs and metrics
  5. Verify application functionality

Zero-Downtime Migration Strategy

For large production databases:

# Phase 1: Add new column (nullable)
def upgrade():
    op.add_column('user', sa.Column('new_email', sa.String(), nullable=True))

# Deploy app version that writes to both columns

# Phase 2: Backfill data
def upgrade():
    op.execute("UPDATE user SET new_email = email WHERE new_email IS NULL")

# Phase 3: Make non-nullable
def upgrade():
    op.alter_column('user', 'new_email', nullable=False)

# Deploy app version that reads from new column

# Phase 4: Drop old column
def upgrade():
    op.drop_column('user', 'email')

Additional Resources

  • Advanced Patterns: See references/advanced-models.md for inheritance, polymorphism, composite keys
  • Migration Guide: See references/migrations.md for Alembic mastery
  • Query Optimization: See references/queries-optimization.md for performance tuning

This skill provides everything needed for professional SQLModel development and database management.

同梱ファイル

※ ZIPに含まれるファイル一覧。`SKILL.md` 本体に加え、参考資料・サンプル・スクリプトが入っている場合があります。