SQLAlchemyで複合キーと関連付けを理解する

この記事ではPythonのORMライブラリ、SQLAlchemyを使って複合キーと関連付け(リレーションシップ)について解説します。具体的なコード例、その詳細な解説、及び応用例を2つ以上を含めています。この記事を通じて、SQLAlchemyでより高度なデータモデリングができるようになります。

目次

はじめに

SQLAlchemyはPythonで利用できるORM(Object Relational Mapper)ライブラリの一つであり、データベース操作をPythonicに行えるように設計されています。今回のテーマである「複合キー」と「関連付け」は、多くの実践的なデータベース設計で出くわす概念であり、その理解と正確な実装は非常に重要です。

複合キーとは

複合キーとは、2つ以上のカラム(フィールド)を組み合わせて、レコード(行)を一意に識別するキーのことです。この複合キーを使用する主な理由は、単一のフィールドだけでは一意性が確保できない場合があるからです。

複合キーの設定方法

SQLAlchemyでは、複合キーは`__table_args__`属性を使用して設定します。

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Example(Base):
    __tablename__ = 'example'
    id = Column(Integer, primary_key=True)
    name = Column(Integer)
    age = Column(Integer)

    __table_args__ = (
        ForeignKeyConstraint(['name', 'age'], ['another_table.name', 'another_table.age']),
    )

このコードにより、`name`と`age`を複合キーとして、`another_table`の`name`および`age`フィールドと関連付けが行われます。

関連付け(リレーションシップ)とは

関連付け(リレーションシップ)とは、2つ以上のテーブル間でデータを連携させる方法です。SQLAlchemyでは`relationship()`関数を使用して、Pythonのクラス間での関連付けを設定します。

関連付けの設定方法

関連付けは`relationship()`関数と、`ForeignKey`クラスを使用して設定します。

from sqlalchemy import relationship

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

この例では、`Parent`クラスと`Child`クラスが一対多の関係を持っていることを表しています。

複合キーと関連付けの組み合わせ

複合キーと関連付けを組み合わせる場面も少なくありません。以下はその一例です。

class GrandChild(Base):
    __tablename__ = 'grandchild'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer)
    parent_id = Column(Integer)

    __table_args__ = (
        ForeignKeyConstraint(['child_id', 'parent_id'], ['child.id', 'parent.id']),
    )

    parent = relationship("Parent", foreign_keys=[parent_id])
    child = relationship("Child", foreign_keys=[child_id])

この例では`GrandChild`が`Parent`と`Child`に対して複合キーを用いた関連付けを行っています。

応用例1:注文と商品

注文(Order)と商品(Product)がある場合、注文詳細(OrderDetail)で複合キーと関連付けを用いることが多いです。

class Order(Base):
    __tablename__ = 'order'
    id = Column(Integer, primary_key=True)
    details = relationship("OrderDetail")

class Product(Base):
    __tablename__ = 'product'
    id = Column(Integer, primary_key=True)

class OrderDetail(Base):
    __tablename__ = 'order_detail'
    order_id = Column(Integer, primary_key=True)
    product_id = Column(Integer, primary_key=True)

    __table_args__ = (
        ForeignKeyConstraint(['order_id', 'product_id'], ['order.id', 'product.id']),
    )

    order = relationship("Order")
    product = relationship("Product")

応用例2:多対多の関連付け

多対多の関連付けでは、中間テーブルが必要になります。

class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)

class Course(Base):
    __tablename__ = 'course'
    id = Column(Integer, primary_key=True)

class Enrollment(Base):
    __tablename__ = 'enrollment'
    student_id = Column(Integer, primary_key=True)
    course_id = Column(Integer, primary_key=True)

    __table_args__ = (
        ForeignKeyConstraint(['student_id', 'course_id'], ['student.id', 'course.id']),
    )

    student = relationship("Student")
    course = relationship("Course")

まとめ

この記事では、SQLAlchemyでの複合キーと関連付けについて詳細に解説しました。これらの概念はデータベース設計において非常に重要です。特に、

多対多の関連付けや注文と商品のような実務でよく見られるケースで役立ちます。

コメント

コメントする

目次