📚
SQLModelのクエリ一覧(SELECT編)
環境設定
バージョン情報
- Python: 3.13.7
- SQLModel: 0.0.31
- DB: SQLite
uvでの環境設定
pyproject.toml
[project]
name = "SQLModelTest"
version = "1.0.0"
description = "SQLModelの動作等を確認する"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"sqlmodel>=0.0.31",
]
[dependency-groups]
dev = [
"mypy>=1.17.1",
"pytest>=8.4.1",
"pytest-cov>=7.0.0",
"pytest-mock>=3.14.1",
"ruff>=0.12.10",
]
この記事で扱わないこと
- Session, Engineの作成
- トランザクション、排他制御
使用するモデル
以降のスクリプトは以下のモデルを使用する前提で記述しています。
article_modelpy
from uuid import UUID, uuid4
from sqlmodel import Field, Session, SQLModel, selec
from app.models import ArticleModel
class ArticleModel(SQLModel, table=True):
"""記事"""
__tablename__ = "article" # type: ignore[assignment]
id: UUID = Field(primary_key=True, default_factory=uuid4, nullable=False)
title: str = Field(nullable=False, description="タイトル")
content: str = Field(nullable=False, description="本文")
status: int = Field(nullable=False, description="記事公開状態(数値)")
SELECT文
IN
集合に含まれる値に一致するレコードを取得します。
in_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def in_query(session: Session) -> None:
"""status が 3 または 4 のレコードを取得する (IN)"""
print("[in_query] status IN (3, 4)")
sql = select(ArticleModel).where(col(ArticleModel.status).in_([3, 4]))
rows = session.exec(sql).all()
NOT IN
集合に含まれない値のレコードを取得します。
not_in_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def not_in_query(session: Session) -> None:
"""status が 3,4 以外のレコードを取得する (NOT IN)"""
print("[not_in_query] status NOT IN (3, 4)")
sql = select(ArticleModel).where(col(ArticleModel.status).not_in([3, 4]))
# もしくは
# sql = select(ArticleModel).where(~col(ArticleModel.status).in_([3, 4]))
rows = session.exec(sql).all()
LIKE
部分一致するレコードを取得します。
like_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def like_query(session: Session) -> None:
"""title が部分一致するレコードを取得する (LIKE)"""
print("[like_query] title LIKE '%テスト%'")
sql = select(ArticleModel).where(col(ArticleModel.title).like("%テスト%"))
rows = session.exec(sql).all()
番外編
CONTAINS
指定した文字列を含むレコードを取得します。
contain_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def contains_query(session: Session) -> None:
"""title が指定文字列を含むレコードを取得する (contains: 内部的に LIKE を組み立て)"""
print("[contains_query] title contains 'テスト'")
sql = select(ArticleModel).where(col(ArticleModel.title).contains("テスト"))
rows = session.exec(sql).all()
STARTSWITH
指定した文字列で始まるレコードを取得します。
startswith_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def startswith_query(session: Session) -> None:
"""title が指定文字列で始まるレコードを取得する (startswith: 内部的に LIKE)"""
print("[startswith_query] title startswith 'テスト'")
sql = select(ArticleModel).where(col(ArticleModel.title).startswith("テスト"))
rows = session.exec(sql).all()
ENDSWITH
指定した文字列で終わるレコードを取得します。
endswith_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def endswith_query(session: Session) -> None:
"""title が指定文字列で終わるレコードを取得する (endswith: 内部的に LIKE)"""
print("[endswith_query] title endswith 'テスト'")
sql = select(ArticleModel).where(col(ArticleModel.title).endswith("テスト"))
rows = session.exec(sql).all()
ILIKE
大文字・小文字を区別せずに部分一致するレコードを取得します。
ilike_querypy
from sqlmodel import Session, col, select
from app.models import ArticleModel
def ilike_query(session: Session) -> None:
"""title が大文字小文字を無視して部分一致するレコードを取得する (ILIKE 相当)
DB 方言により生成される SQL が変わります (PostgreSQL なら ILIKE など)
"""
print("[ilike_query] title ILIKE '%test%' (DB方言により変化)")
sql = select(ArticleModel).where(col(ArticleModel.title).ilike("%test%"))
rows = session.exec(sql).all()
AND
複数の条件を連結し、AND条件でレコードを取得します。
and_query
from sqlmodel import Session, col, select
from app.models import ArticleModel
def and_query(session: Session) -> None:
"""複数の where を連結して AND 条件で取得する。"""
print("[and_query] (status IN (3,4)) AND (title LIKE '%テスト%')")
sql = (
select(ArticleModel)
.where(col(ArticleModel.status).in_([3, 4]))
.where(col(ArticleModel.title).like("%テスト%"))
)
rows = session.exec(sql).all()
OR
OR条件でレコードを取得します。
or_query
from sqlmodel import Session, col, select
from app.models import ArticleModel
def or_query(session: Session) -> None:
"""OR 条件で取得する"""
print("[or_query] (status = 3) OR (title LIKE '%テスト%')")
sql = select(
ArticleModel
).where(
(ArticleModel.status == 3)|(col(ArticleModel.title).like("%テスト%"))
)
rows = session.exec(sql).all()
ORDER BY句 / LIMIT句 / OFFSET句
並び替えとページングを行い、レコードを取得します。
order_limit_offset_query.py
from sqlmodel import Session, col, select
from app.models import ArticleModel
def order_limit_offset_query(session: Session) -> None:
"""並び替え+ページング (ORDER BY / LIMIT / OFFSET)
ArticleModel に `id` カラムがある場合のみ実行します。
"""
print("[order_limit_offset_query] ORDER BY id DESC LIMIT 5 OFFSET 0")
sql = select(ArticleModel).order_by(col(ArticleModel.id).desc()).limit(5).offset(0)
rows = session.exec(sql).all()
終わりに
まだメジャーバージョンではないので情報が古くなる可能性が高いですが、
SQLModel使用時の助けになれば幸いです。
Discussion