データベース

SQLModelとは?SQLAlchemyとPydanticを統合したPython製ORMの特徴と使い方

SQLModelは、データベース操作のSQLAlchemyと、型に基づくデータ検証のPydanticを1つのモデルクラスに統合したPython製のORMです。FastAPIの作者であるSebastián Ramírez(tiangolo)が開発し、テーブル定義とAPIの入出力バリデーションを同じクラスで表現できる点が最大の特徴です。この記事では、SQLModelの定義、最小構成の使い方、SQLAlchemyとの違いと使い分け、FastAPI・Pydanticとの関係、そして採用を避けたほうがよい場面までを、公式仕様と最新バージョン(0.0.39)に沿って整理します。

まとめ:SQLModelは「定義とバリデーションを一体化するORM」

SQLModelは、SQLAlchemyのテーブル定義とPydanticの型検証を1クラスにまとめ、FastAPIと組み合わせたAPI開発でコードの重複を減らすためのORMです。既存のSQLAlchemyコードと同じエンジン・セッションを使うため学習コストは低い一方、2026年7月時点でもバージョンは0.0.39と1.0未満で、リレーションや非同期まわりはSQLAlchemyの知識が前提になります。小〜中規模のFastAPIアプリで型安全にCRUDを組みたいなら有力候補、複雑なクエリや高度な非同期制御が中心なら素のSQLAlchemyのほうが向きます。以降で、定義・基本コード・SQLAlchemyとの違い・採用可否の判断基準を具体的に見ていきます。

SQLModelとは何か:SQLAlchemyとPydanticを1クラスに統合するORM

SQLModelは、リレーショナルデータベースをPythonのオブジェクトとして扱うORMの一種です。内部ではSQLAlchemyのCore/ORMをそのまま利用してテーブル定義やクエリを行い、同時にPydanticのモデルとして型ヒントに基づくデータ検証・シリアライズを担います。つまり「DBのテーブル」と「APIで受け渡すデータモデル」を別々のクラスで二重定義せず、1つのクラスにまとめられるのがSQLModelの核心です。

従来のFastAPI+SQLAlchemy構成では、テーブル用のSQLAlchemyモデルと、リクエスト・レスポンス用のPydanticモデルを別々に書くのが定石でした。SQLModelはこの2つを橋渡しし、同じフィールド定義を使い回せるようにします。読み方は「エスキューエル・モデル」で、パッケージ名・インポート名ともにsqlmodelです。

SQLModelが解決する課題:型安全とバリデーションの二重定義

SQLAlchemy単体では、DB操作はできても入力値が正しい型・形式かを保証する仕組みは標準にありません。そのため実務ではPydanticを別途組み合わせ、同じ「ユーザー」を表すのにテーブル用クラスとAPI用クラスを二重に定義しがちでした。SQLModelは、テーブルにもなりPydanticの検証も効く単一のクラスを提供することで、この二重定義とそれに伴う変換コードを減らします。フィールドに型ヒントを付けるだけで、IDEの補完・型チェックとDBカラム定義が同時に決まります。

開発状況とバージョン:2026年時点で0.x系である点に注意

SQLModelの最新版は0.0.39(2026年6月25日リリース、対応Python 3.10以上)で、公開開始から数年を経てもメジャーバージョンは1.0に到達していません。実務投入例は増えていますが、APIやリレーション周辺の挙動は将来変わり得るため、本番採用時はバージョンを固定し、公式ドキュメント(sqlmodel.tiangolo.com)で最新の対応状況を確認するのが安全です。Pydanticはv2に対応済みで、v2系の検証機能をそのまま利用できます。

SQLModelの基本的な使い方:インストールからモデル定義・データ操作まで

SQLModelはSQLAlchemyとPydanticを依存に持つため、pipで導入すれば必要なライブラリが一緒に入ります。ここでは最小構成で「インストール→モデル定義→保存→取得」までの流れを示します。より実務的なモデル設計やテーブル初期化の手順は、SQLModelを用いた基本的なモデル定義とテーブル作成の方法で具体的に解説しています。

インストール:pipでsqlmodelを導入する

対応Pythonは3.10以上です。仮想環境を有効にしたうえで、次のコマンドで導入します。

pip install sqlmodel

これでSQLAlchemyとPydanticも同時にインストールされます。バージョンを固定したい場合はpip install "sqlmodel==0.0.39"のように明示します。

モデル定義:SQLModelを継承しtable=Trueを付ける

テーブルにするクラスはSQLModelを継承し、table=Trueを指定します。各フィールドは型ヒントで宣言し、主キーやデフォルト値はFieldで設定します。主キーは自動採番を想定してint | None(Optional)にし、デフォルトをNoneにするのが正しい書き方です。

from sqlmodel import SQLModel, Field

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    age: int | None = Field(default=None, index=True)

idint | Noneにするのは、レコード作成時点ではまだ採番されておらず値がNoneになるためです。index=Trueを付けたフィールドには検索用インデックスが張られます。

データ操作:session.exec(select())で書くのが正しい

エンジンを作り、SQLModel.metadata.create_all()でテーブルを作成したら、Sessionでレコードを追加・取得します。取得はselect()文をsession.exec()に渡す形がSQLModelの標準です。SQLAlchemy 1.x系スタイル(レガシー)のsession.query(...)も動きはしますが、SQLModelでは型情報が効くsession.exec(select(...))が推奨で、公式チュートリアルもこちらで統一されています。

from sqlmodel import SQLModel, Session, create_engine, select
# Heroは前段で定義したモデルクラス

engine = create_engine("sqlite:///database.db")
SQLModel.metadata.create_all(engine)

with Session(engine) as session:
    session.add(Hero(name="Deadpond", age=48))
    session.commit()

    heroes = session.exec(select(Hero).where(Hero.age > 40)).all()

with文でSessionを開けば、処理終了時に自動でクローズされ接続リークを防げます。select(Hero)が返すのは型付きのHeroオブジェクトなので、heroes[0].nameのようにエディタ補完が効きます。session.query()で書かれた古いサンプルを見かけたら、session.exec(select())へ読み替えるのが安全です。

SQLModelとSQLAlchemyの違いと使い分け

SQLModelはSQLAlchemyの上に構築されているため対立関係ではなく、「SQLAlchemy+Pydanticをまとめた薄い層」と捉えると分かりやすいです。DB操作の中身はSQLAlchemyそのもので、そこに型検証と単一クラス化を足したのがSQLModelです。両者の主な差は次の通りです。

観点 SQLModel SQLAlchemy(単体)
データ検証 Pydantic統合で標準装備 別途Pydantic等が必要
モデル定義 型ヒント中心・1クラス Column中心・API/DBは別クラス
FastAPI連携 同一クラスを流用可 変換コードが増えやすい
成熟度 0.x系(発展途上) 2.x系・実績豊富
複雑なクエリ SQLAlchemyの機能に委譲 細かく制御可能

SQLAlchemyそのものの基礎を先に押さえたい場合は、SQLAlchemyとは?Python ORMの基本と使い方を参照すると、SQLModelがどこを肩代わりしているかが理解しやすくなります。

どちらを選ぶか:判断基準

選定はプロジェクトの性格で決まります。FastAPIでAPIを作り、テーブルと入出力モデルを型安全に一体化したい小〜中規模開発なら、二重定義を減らせるSQLModelが有利です。一方、複雑なJOINやサブクエリ、細かなトランザクション制御、成熟したエコシステム(プラグインや実績あるパターン)を重視する大規模・高度なDB処理では、SQLAlchemyを直接使うほうが自由度と情報量で勝ります。迷う場合は「FastAPIが主役かどうか」を基準にすると判断しやすく、FastAPI中心ならSQLModel、DB層が主役ならSQLAlchemyが目安です。

SQLModelとFastAPI・Pydanticの関係

SQLModelはPydanticのモデルとしても振る舞うため、FastAPIのエンドポイントで受け取るリクエストボディやレスポンスの型として、テーブル用クラスをそのまま利用できます。FastAPIはPydanticで入力検証を行う設計なので、SQLModelのクラスを渡すだけで型に基づくバリデーションが自動で走り、不正な入力にはエラーが返ります。テーブル定義とAPIスキーマを1クラスで共有できるのが、この組み合わせの利点です。

ただし実務では、テーブル用(table=True)と、APIの入出力用(table=Trueを付けないPydanticとしてのSQLModel)を役割ごとに分けるのが定石です。全フィールドをそのままAPIに露出させると、主キーや内部項目まで受け付けてしまうためです。Pydantic側の基礎はPydanticとは?Pythonデータ検証ライブラリの使い方、v2での変更点はPydantic v2の概要と特徴で確認できます。FastAPIとDB層の組み方全般はFastAPIとSQLAlchemyでのモデルの構築方法とベストプラクティスが参考になります。

SQLModelの採用を避けたほうがよい場面と注意点

SQLModelは便利ですが、万能ではありません。次のような場合は、無理に採用せずSQLAlchemyを直接使う判断が妥当です。

  • 本番で高い安定性が要求される基幹システム:0.x系のため、将来のバージョンアップでAPIやリレーションの挙動が変わる可能性がある。採用するならバージョン固定と回帰テストを前提にする。
  • 複雑なリレーションを多用する設計:リレーション定義はSQLAlchemyのRelationshipを踏襲しており、結局SQLAlchemyの知識が必要になる。SQLModel特有の抽象で楽になるわけではない。
  • 本格的な非同期処理が中心のアプリ:後述の落とし穴があり、同期前提のサンプルが多いため設計に注意が要る。

非同期の落とし穴:async defにするだけでは非同期にならない

よくある誤りが、FastAPIのエンドポイントをasync defにしただけで、中で同期のSessionを使ってしまうパターンです。これはDBアクセス中にイベントループをブロックするため、非同期化の効果が得られません。SQLModelで真に非同期化するには、sqlmodel.ext.asyncio.sessionAsyncSessionと、create_async_engineによる非同期エンジンを使い、await session.exec(...)のように待ち受ける必要があります(対応する非同期DBドライバも別途必要)。同期SessionをそのままasyncのなかへコピペしたコードはWeb上に多いため、鵜呑みにせず、AsyncSession版かどうかをimport行で確認するのが安全です。

よくある質問

SQLModelとSQLAlchemyはどちらを使うべきですか?

FastAPIでAPIを作り、テーブルと入出力モデルを型安全に一体化したい小〜中規模開発ならSQLModel、複雑なクエリや高度な制御・豊富な実績を重視する大規模開発ならSQLAlchemyを直接使うのが目安です。SQLModelは内部でSQLAlchemyを使うため、両者は排他ではありません。

SQLModelは本番運用に使えますか?

使用例は増えていますが、2026年7月時点でも0.0.39と1.0未満です。採用する場合はバージョンを固定し、公式ドキュメントで対応状況を確認したうえで、テストを整備して運用するのが安全です。

SQLModelの最新バージョンは何ですか?

PyPI上の最新は0.0.39(2026年6月25日リリース、対応Python 3.10以上)です。バージョンは変動するため、導入前にpip index versions sqlmodelや公式サイトで最新を確認してください。

SQLModelを使うにはFastAPIが必須ですか?

必須ではありません。SQLModel単体でORMとして使えます。ただしFastAPIの作者が開発しており、FastAPIと組み合わせたときにテーブルと入出力モデルを共有できる利点が最も活きます。

session.query()はSQLModelでも使えますか?

SQLAlchemy由来のため動作はしますが、SQLModelでは型情報が効くsession.exec(select(Model))が推奨で、公式チュートリアルもこちらで統一されています。新規に書くコードはselect()ベースに揃えるのがよいです。

関連記事

資料請求

RELATED POSTS 関連記事