Pythonで始めるSQLAlchemy入門:ORMの基本から実践まで

Webアプリやデータ分析でデータベースを扱うとき、SQLを直接書くのは大変です。

Pythonでオブジェクト指向のままデータ操作ができるORM(Object Relational Mapper)の代表格が SQLAlchemy です。

本記事では、SQLAlchemyの基本概念からモデル定義、CRUD操作、リレーション設定までを丁寧に解説します。初心者でもつまづかないように、シンプルな例を交えて進めていきます。


SQLAlchemyとは?

ORM(Object Relational Mapper)

PostgreSQLやMySQLなどのリレーショナルDBを、Pythonのクラスとオブジェクトとして扱える仕組み。

コアとORM
  • Core:SQLを直接組み立てる低レイヤーAPI
  • ORM:Coreを内包し、クラス定義でSQLを自動生成

ORMを使うことで、生SQLを書く手間を減らし、モデル定義に集中できます。


環境構築

# 仮想環境の作成
python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate

# SQLAlchemy本体とSQLiteドライバをインストール
pip install SQLAlchemy

※ SQLiteは組み込み型の軽量DBで、試学習に最適です。
※ 本番では pip install psycopg2-binary などでPostgreSQLドライバを追加します。


EngineとSessionの使い方

Engineは、データベースへの接続情報を保持し、Core APIでSQLを実行できるオブジェクトです。

Sessionは、オブジェクト単位でのトランザクション管理・CRUD操作を担うオブジェクトです。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# Engine生成(SQLiteファイル:test.db を使用)
engine = create_engine("sqlite:///test.db", echo=True)

# Sessionクラス生成
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)

# Sessionインスタンス作成
session = SessionLocal()

echo=True を付けると実行されるSQLがログとして出力され、学習に便利です。


モデル定義(テーブル設計)

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = "users"            # テーブル名
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), nullable=False)
    email = Column(String(120), unique=True, nullable=False)

# テーブル作成
Base.metadata.create_all(bind=engine)

declarative_base() でベースクラスを作成し、各フィールドは Column で定義し、Pythonの属性として扱います。


CRUD操作

作成(Create)

new_user = User(name="山田太郎", email="taro@example.com")
session.add(new_user)
session.commit()     # DBに確定
session.refresh(new_user)  # 自動生成されたIDなどを取得
print(new_user.id)

読み取り(Read)

# 全件取得
users = session.query(User).all()

# 条件付き取得
user = session.query(User).filter(User.email=="taro@example.com").first()

更新(Update)

user = session.query(User).get(1)
user.name = "山田次郎"
session.commit()

削除(Delete)

user = session.query(User).get(1)
session.delete(user)
session.commit()

リレーション(1対多、多対多)

1対多の例

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship

class Post(Base):
    __tablename__ = "posts"
    id = Column(Integer, primary_key=True)
    title = Column(String(100))
    content = Column(String(500))
    user_id = Column(Integer, ForeignKey("users.id"))

    author = relationship("User", back_populates="posts")

User.posts = relationship("Post", back_populates="author")
Base.metadata.create_all(bind=engine)

relationship() でPythonオブジェクト同士の関係を定義します。


実践例:ブログ記事管理アプリ

  1. モデル定義:User と Post を用意
  2. 新規ユーザー・記事作成
  3. 記事一覧・詳細表示
  4. 編集・削除機能

実際のWebアプリ(Flask/Django)に組み込むと、URLルーティング→View→CRUD操作という流れで実装できます。


演習問題

以下の問題に取り組んで、理解を深めましょう。

  1. モデル定義
    Category テーブルを作成し、id, name, description をフィールドとして定義してください。
  2. 1対多リレーション
    1つの Category が複数の Post を持つ関係を設定し、Category.posts と Post.category の relationship を定義してください。
  3. データ挿入
    Category(name=”Python”, description=”Python関連の記事”) とし、2つ以上の Post を紐付けて保存してください。
  4. クエリ
    Python カテゴリに属する記事タイトル一覧を取得するクエリを作成してください。
  5. 更新・削除
    特定の Category の description を更新し、ある Post を削除するコードを書いてください。

解答例

# 1. モデル定義
class Category(Base):
    __tablename__ = "categories"
    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    description = Column(String(200))

# 2. リレーション設定
class Post(Base):
    # 既存の定義に追加
    category_id = Column(Integer, ForeignKey("categories.id"))
    category = relationship("Category", back_populates="posts")

Category.posts = relationship("Post", back_populates="category")

# テーブル作成
Base.metadata.create_all(bind=engine)

# 3. データ挿入
python_cat = Category(name="Python", description="Python関連の記事")
post1 = Post(title="はじめてのSQLAlchemy", content="内容...", author=new_user, category=python_cat)
post2 = Post(title="リレーション入門", content="内容...", author=new_user, category=python_cat)
session.add_all([python_cat, post1, post2])
session.commit()

# 4. クエリ
results = (
    session.query(Post.title)
    .join(Category)
    .filter(Category.name == "Python")
    .all()
)
for title, in results:
    print(title)

# 5. 更新・削除
# 更新
cat = session.query(Category).filter_by(name="Python").first()
cat.description = "Python関連記事をまとめたカテゴリ"
session.commit()

# 削除
post_to_delete = session.query(Post).get(post1.id)
session.delete(post_to_delete)
session.commit()

まとめ

本記事では、Pythonからデータベース操作を楽にするORMフレームワーク SQLAlchemy の基本を解説しました。

  • Engine/Session の理解
  • モデル定義 → テーブルの作成
  • CRUD 操作
  • リレーション 設定
  • 演習問題 で実践

これらを身につけることで、Webアプリ開発やデータ分析でのDB操作が飛躍的に楽になります。

次のステップとして、FlaskやDjangoと組み合わせたり、PostgreSQLなど他DBで動かしてみてください。

SQLAlchemyの豊富な機能を使いこなし、効率的な開発ライフを実現しましょう!