コンテンツにスキップ

PythonのSQLサンプル

[質問]

Pythonのsqlite3モジュールを利用し、次のSQLでDBのテーブルを作りました。

CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    text TEXT NOT NULL,
    created_at DATETIME DEFAULT (DATETIME('now', 'localtime'))
)

このテーブルに対し、次の処理を行うPythonコードを教えてください。

  1. 新しい text を追加する。
    INSERT INTO posts (text) VALUES (?)
  2. すべてのレコードを取得する。
    SELECT * FROM posts ORDER BY created_at DESC
  3. textをキーワードで検索する。
    SELECT * FROM posts WHERE text LIKE (?) ORDER BY created_at DESC
  4. レコードを削除する。
    DELETE FROM posts WHERE id = (?)

[回答] Gemini

Pythonのsqlite3標準ライブラリを使って、これらの操作をまとめたサンプルコードを作成しました。

SQLiteは、接続(connect)した後に、命令を実行するためのカーソル(cursor)を取得して操作するのが基本の流れです。

SQLite操作のPythonコード例

import sqlite3

def get_connection():
    # 'my_database.db' というファイル名でDBを作成/接続
    return sqlite3.connect('my_database.db')

def create_table():
    conn = get_connection()
    cur = conn.cursor()
    cur.execute("""
    CREATE TABLE IF NOT EXISTS posts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        text TEXT NOT NULL,
        created_at DATETIME DEFAULT (DATETIME('now', 'localtime'))
    )
    """)
    conn.commit()
    conn.close()

# 1. 新しい text を追加する
def add_post(text):
    conn = get_connection()
    cur = conn.cursor()
    cur.execute("INSERT INTO posts (text) VALUES (?)", (text,))
    conn.commit()
    conn.close()

# 2. すべてのレコードを取得する
def get_all_posts():
    conn = get_connection()
    cur = conn.cursor()
    cur.execute("SELECT * FROM posts ORDER BY created_at DESC")
    rows = cur.fetchall()
    conn.close()
    return rows

# 3. textをキーワードで検索する
def search_posts(keyword):
    conn = get_connection()
    cur = conn.cursor()
    # 部分一致のため、キーワードを % で囲む
    query_param = f"%{keyword}%"
    cur.execute("SELECT * FROM posts WHERE text LIKE (?) ORDER BY created_at DESC", (query_param,))
    rows = cur.fetchall()
    conn.close()
    return rows

# 4. レコードを削除する
def delete_post(post_id):
    conn = get_connection()
    cur = conn.cursor()
    cur.execute("DELETE FROM posts WHERE id = (?)", (post_id,))
    conn.commit()
    conn.close()

# --- 動作確認 ---
if __name__ == "__main__":
    create_table()

    # 追加
    add_post("こんにちは、Pythonの世界!")
    add_post("SQLiteはとても便利ですね。")

    # 検索(「Python」を含むもの)
    print("--- 検索結果 ---")
    results = search_posts("Python")
    for row in results:
        print(row)

    # 全件取得
    print("\n--- 全件表示 ---")
    all_posts = get_all_posts()
    for row in all_posts:
        print(row)

    # 削除(例として最初の1件を削除)
    if all_posts:
        delete_post(all_posts[0][0])
        print(f"\nID {all_posts[0][0]} を削除しました。")

💡 実装のポイント

  • プレースホルダ (?) の使用: SQL文の中に直接変数を書き込まず(f-stringなどを使わず)、必ず ? を使って第二引数のタプルで値を渡してください。これは SQLインジェクション という攻撃を防ぐための必須の作法です。
  • commit() の忘れ物に注意: INSERTDELETE など、データを書き換える操作をした後は conn.commit() を呼ばないと、変更が確定されません。
  • LIKE検索のワイルドカード: LIKE を使った部分一致検索の場合、Python側でキーワードを %keyword% のように加工してから渡すとスムーズです。

次は、取得したデータを扱いやすくするために、タプルではなく辞書形式(row["text"] のようにアクセスできる形)で取得する方法を解説しましょうか?