Pythonの sqlite3 モジュールでは、デフォルトのデータ取得形式はタプル(tuple)ですが、設定を変更することで辞書のように「カラム名」を指定して値にアクセスすることが可能になります。これにより、SQLのSELECT文で取得したカラムの順序を気にする必要がなくなり、コードの可読性が大幅に向上します。
ここでは、sqlite3.Row を使用してカラム名でデータを取り出す具体的な実装方法を解説します。
目次
実行可能なサンプルコード
以下のコードは、図書館の蔵書管理を想定したデータベースを作成し、カラム名(title や author など)を指定してデータを取得する完全なスクリプトです。
import sqlite3
import os
# データベースファイル名
DB_FILE = "library_catalog.db"
def setup_database():
"""テスト用のデータベースとテーブルを作成し、データを投入する"""
if os.path.exists(DB_FILE):
os.remove(DB_FILE)
with sqlite3.connect(DB_FILE) as conn:
cursor = conn.cursor()
# テーブル作成
cursor.execute("""
CREATE TABLE books (
book_id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
published_year INTEGER
)
""")
# データ挿入
sample_books = [
('The Great Gatsby', 'F. Scott Fitzgerald', 1925),
('1984', 'George Orwell', 1949),
('To Kill a Mockingbird', 'Harper Lee', 1960),
('Brave New World', 'Aldous Huxley', 1932)
]
cursor.executemany(
"INSERT INTO books (title, author, published_year) VALUES (?, ?, ?)",
sample_books
)
conn.commit()
def main():
# データベースの準備
setup_database()
print("=== カラム名によるデータアクセス ===")
with sqlite3.connect(DB_FILE) as conn:
# 重要な設定: 行ファクトリにsqlite3.Rowを指定
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
# パターン1: カーソルループでのアクセス
print("\n--- 1. Cursor Loop Access ---")
cursor.execute("SELECT * FROM books")
for row in cursor:
# カラム名でアクセス可能
print(f"ID: {row['book_id']} | Title: {row['title']}")
# パターン2: fetchall()でのアクセス
print("\n--- 2. fetchall() Access ---")
cursor.execute("SELECT * FROM books WHERE published_year > 1940")
rows = cursor.fetchall()
for row in rows:
# 辞書のように扱えるが、実体はsqlite3.Rowオブジェクト
print(f"Title: {row['title']}, Author: {row['author']}")
# パターン3: fetchone()でのアクセス
print("\n--- 3. fetchone() Access ---")
cursor.execute("SELECT * FROM books ORDER BY published_year DESC")
# 1件目取得
first_book = cursor.fetchone()
if first_book:
print(f"Latest Book: {first_book['title']} ({first_book['published_year']})")
# 2件目取得
second_book = cursor.fetchone()
if second_book:
print(f"Next Book: {second_book['title']} ({second_book['published_year']})")
if __name__ == "__main__":
main()
解説:sqlite3.Row の仕組み
conn.row_factory = sqlite3.Row
通常、sqlite3 は結果を (1, 'The Great Gatsby', 'F. Scott Fitzgerald') のようなタプルで返します。しかし、コネクションオブジェクトの row_factory 属性に sqlite3.Row クラスを設定することで、返却されるオブジェクトが高機能な Row オブジェクトに変わります。
Rowオブジェクトの特徴
このオブジェクトはハイブリッドな特性を持っており、以下の両方の方法でデータにアクセスできます。
- インデックス番号:
row[0](従来のタプルと同様) - カラム名:
row['title'](辞書のようなアクセス) - 大文字・小文字の区別なし: SQLの仕様に準じ、カラム名の大文字小文字を区別せずにアクセス可能です(環境によっては区別される場合もあるため、正確なカラム名を使用することを推奨します)。
辞書型(dict)への変換
sqlite3.Row オブジェクトはそのままでは JSON シリアライズなどができません。純粋な辞書型として扱いたい場合は、以下のように変換します。
book_dict = dict(row)
print(book_dict)
# 出力例: {'book_id': 1, 'title': 'The Great Gatsby', ...}
