python SQLAlchemy データベース連携

Python

SQLAlchemyは、Pythonでデータベース操作を簡素化するためのライブラリです
主にSQLデータベースとやり取りするために使用されます

SQLAlchemyの概要

SQLAlchemyは、データベースにアクセスするための2つの主要なパラダイムを提供します:

  1. Core(SQL Expression Language)
    • 低レベルでSQLクエリを構築し、実行するためのインターフェース
    • 手動でSQLを作成し、細かい制御を行いたい場合に適しています
  2. ORM(Object Relational Mapper)
    • 高レベルな抽象化を提供し、PythonオブジェクトをSQLデータベースのテーブルとマッピングします
    • オブジェクト指向プログラミングの概念をデータベース操作に適用することで、直感的な操作が可能です

SQLAlchemyの主な特徴

  1. データベース非依存性
    • データベースエンジン(SQLite, MySQL, PostgreSQL, Oracle, SQL Serverなど)をサポートしています
    • データベースエンジンを切り替える場合も、コードの変更が最小限で済みます
  2. ORM(Object Relational Mapping)
    • Pythonクラスをデータベーステーブルに対応させ、Pythonオブジェクトを使ってデータの挿入、更新、削除、検索ができます
    • SQLの知識がなくてもデータベースを扱いやすくなります
  3. トランザクション管理
    • トランザクションの自動管理や手動制御が簡単にできます
  4. モジュール性
    • 必要な部分だけを選んで使用できるため、軽量な実装も可能です

今回はデータベースにSQLite(エスキューライト)を使用します
SQLiteは、初心者でも理解しやすい軽量で自己完結型のデータベース管理システム(DBMS)です

SQLiteの主な特徴

  1. 軽量で組み込み型
    • SQLiteは非常に軽量で、外部サーバーを必要としない組み込み型のデータベースです
      アプリケーションに直接組み込んで使用できます
  2. 自己完結型
    • SQLiteは単一のファイル(.sqliteや.dbなどの拡張子)にすべてのデータを格納します
      そのため、簡単にデータを移動・バックアップできます
  3. サーバーレス
    • サーバープロセスを必要としないため、クライアントとサーバー間の通信が不要です
    • アプリケーションが直接SQLiteのファイルにアクセスします
  4. SQLサポート
    • 標準的なSQL(Structured Query Language)をサポートしており、クエリ、トランザクション、インデックス、ビューなどの基本機能を利用できます
  5. 高い信頼性
    • SQLiteはACID(Atomicity, Consistency, Isolation, Durability)特性を備えており、安全で信頼性の高いデータ処理が可能です
  6. クロスプラットフォーム
    • Windows、Linux、macOS、モバイルデバイス(iOSやAndroid)など、さまざまなプラットフォームで動作します
  7. オープンソース
    • SQLiteはオープンソースであり、無償で利用できます

・環境

SQLAlchemy 2.0.36
pandas 2.2.3

・ライブラリをインストール

pip install pandas sqlalchemy

・実行コード

最初に全体のコードを以下に書いてから、詳細を解説していきます

import pandas as pd
from sqlalchemy import create_engine, Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# データベース接続設定
DATABASE_URL = "sqlite:///example.db"  # SQLiteを使用する例
engine = create_engine(DATABASE_URL, echo=True)

# ベースクラス作成
Base = declarative_base()

# テーブル定義
class ExampleTable(Base):
    __tablename__ = 'example_table'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String, nullable=False)
    age = Column(Integer, nullable=False)
    score = Column(Float, nullable=False)

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

# CSVファイルの読み込み
csv_file = "example.csv"  # CSVファイルのパス
df = pd.read_csv(csv_file)

# データベースにデータを書き込む
Session = sessionmaker(bind=engine)
session = Session()

try:
    # DataFrameのデータをテーブルに挿入
    for _, row in df.iterrows():
        record = ExampleTable(
            name=row['name'],
            age=row['age'],
            score=row['score']
        )
        session.add(record)
    session.commit()
    print("データが正常に挿入されました!")
except Exception as e:
    session.rollback()
    print(f"エラーが発生しました: {e}")
finally:
    session.close()

読み込むcsvファイルの内容

name,age,score
Alice,25,85.5
Bob,30,90.0
Charlie,22,78.0

・コードの解説

上から順番にコードの解説をします

DATABASE_URL = “sqlite:///example.db”
これは、データベース接続文字列(接続URL)を定義している部分です

以下のような構成になっています
・dialect+driver://username:password@host:port/database
 dialect: 使用するデータベースの種類を指定します(例: sqlite, mysql, postgresql など)

・driver: データベース接続に使用するPythonのドライバを指定します(省略可能)
 sqliteではデフォルトのドライバが使われるため、通常は指定不要です

・username:password: データベースにログインするためのユーザー名とパスワードです(SQLiteで  は不要)

・host:port: データベースサーバーのホスト名とポート番号(SQLiteでは不要)
 database: 接続するデータベースの名前、またはファイルのパス

今回のコード
sqlite:SQLiteという軽量なデータベースを指定
example.db:現在のディレクトリに作成または接続するSQLiteデータベースファイル
このコードは「example.db という名前のSQLiteデータベースに接続する」ことを示しています

engine = create_engine(DATABASE_URL, echo=True)
SQLAlchemyのcreate_engineという関数を使用して、データベース接続用の「エンジン」を作成しています
作成されたエンジンオブジェクトは、データベース操作に使用されます

・引数
DATABASE_URL:
接続先のデータベースを指定します(上記で説明したURL)
SQLite、MySQL、PostgreSQLなど、さまざまなデータベースに対応しています

echo=True:
デバッグ目的で使用されるオプションです。
このオプションを有効にすると、SQLAlchemyは内部で実行されるすべてのSQL文を標準出力(コンソール)に表示します
開発やデバッグ時には役立ちますが、本番環境では通常Falseに設定します

・エンジンの役割
 エンジンはデータベースとの接続を管理する「インターフェース」の役割を果たします
 SQLAlchemyのSessionオブジェクトやCore APIを使用してクエリを実行する際に、このエンジンを   介してデータベース操作が行われます

Base = declarative_base()
これはSQLAlchemyの「ORM(オブジェクトリレーショナルマッピング)」を使用するためのベースクラスを作成するコードです

declarative_base()
SQLAlchemyのdeclarativeシステムを使ってテーブルを定義する際に必要な基底クラス(Base)を生成します
このクラスを継承してテーブルをPythonのクラスとして定義します。
このコードによって、テーブル定義やデータベースとのマッピングを簡潔に行えるようにします
このベースクラスは、定義されたクラスとデータベースのテーブル構造をリンクさせる役割を持っています

class ExampleTable(Base):
ここでは、データベーステーブルをPythonのクラスとして定義しています

・Baseの継承
 ExampleTableクラスは、先ほど作成したBaseクラスを継承しています。
 継承することで、このクラスがSQLAlchemyのORMで扱える「テーブルクラス」であると認識されます

__tablename__
データベース上で使用されるテーブルの名前を指定します
この例では、example_tableという名前のテーブルを作成します

id = Column(Integer, primary_key=True, autoincrement=True)
この行は、idというカラム(列)をテーブルに定義しています

・Column:
 データベーステーブルの列を定義するためのクラスです
・Integer:
 列のデータ型として整数型を指定します
・primary_key=True:
 この列を主キー(テーブルの一意性を保証するキー)として設定します
・autoincrement=True:
 新しいレコードが挿入される際に、自動的に値をインクリメント(1ずつ増加)させます

この行はインデックスキーとしてテーブルの主キーとして使われる「id」列を定義しています
主キーは、各行を一意に識別するために使用されます

name = Column(String, nullable=False)
この行は、文字列型のnameというカラムを定義しています

String:
列のデータ型として文字列型を指定します
nullable=False:
この列にNULL(値が未設定)を許可しない設定です

age = Column(Integer, nullable=False)
この行は、整数型のageというカラムを定義しています

score = Column(Float, nullable=False)
この行は、浮動小数点数型のscoreというカラムを定義しています

この部分はSQLAlchemyのORMを使ってexample_tableという名前のデータベーステーブルを定義しています


Base.metadata.create_all(engine)

テーブルを作成します

  • Base.metadata:
    declarative_base()で作成したベースクラスに関連付けられたメタデータオブジェクトです
    定義されたすべてのテーブル情報を保持しています
  • create_all(engine):
    SQLAlchemyが保持するテーブル定義に基づいて、実際のデータベースにテーブルを作成します
    この場合、engine(データベース接続情報)を使用してテーブルが作成されます
    すでに存在するテーブルは再作成されません(安全性のため)


csv_file = “example.csv” # CSVファイルのパス
df = pd.read_csv(csv_file)
pd.read_csv

pandasライブラリの関数を使用して、指定したCSVファイル(example.csv)を読み込み、DataFrame形式のデータ構造に変換しています


Session = sessionmaker(bind=engine)
session = Session()

セッションの作成をします

  • sessionmaker:
    SQLAlchemyでデータベースとのやり取りを行う際に使用するセッションを作成するファクトリ関数です
  • bind=engine:
    セッションを作成するときに使用するデータベース接続(エンジン)を指定します
    セッションの役割セッションは、データベースとのトランザクションを管理します
    データの追加、更新、削除、クエリの実行などを行います
  • セッションオブジェクト(session)は、エンジンを通じてデータベースと通信します

for _, row in df.iterrows():
record = ExampleTable(
name=row[‘name’],
age=row[‘age’],
score=row[‘score’]
)
session.add(record)
session.commit()

データの挿入をします

  • for _, row in df.iterrows():
    DataFrame(df)の各行をイテレートします
    df.iterrows()とは、DataFrameの各行を1つずつ返す「イテレータ」を作成します
    _(アンダーバー)は行のインデックス(index)を、rowには、現在の行のデータ(name, age, scoreなど)を示します
  • record = ExampleTable
    CSVファイルの各行データを使用して、ExampleTableクラスのインスタンス(record)を作成します
  • session.add(record):
    作成したインスタンスをセッションに追加します
    この時点ではまだデータベースには書き込まれません
  • session.commit():
    セッションに追加されたすべての操作を確定し、実際にデータベースに挿入します


except Exception as e:
session.rollback()

データの挿入中にエラーが発生した場合、session.rollback()でトランザクションをロールバック(取り消し)し、エラーメッセージを出力します

finally:
session.close()

セッションを必ず閉じるための処理です(リソースの解放)

長くなりましたが、以上のコードでpython SQLAlchemy を使ってsqliteのデータベース連携、保存する方法を解説しました

これ単体で使うことは少ないと思いますが、flaskやdjangoなどのwebアプリケーションには必要な内容なので、基礎から理解することが大切だと思います

コメント