基礎から学ぶPython入門 90日コース | データベース・Web API - Day 66:SQLite × Python

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 66:SQLite × Python ― 小さくて頼れる「顧客管理CLIアプリ」を作る

Day 66では、ここまで学んできた SQLitePython を組み合わせて、 実際に動く 顧客管理CLIアプリ を作っていきます。

  • データベースのテーブル設計
  • INSERT / SELECT / UPDATE / DELETE
  • SQLiteとPythonの連携

これらをひとつの「作品」にまとめるイメージです。

「ちょっとした顧客リストを管理したい」「Excelだと心もとない」 そんなときに、自分で作ったCLIアプリが動いてくれたら、かなり嬉しいですよね。

今日は、その“最初の一歩”になるような、 シンプルだけれど実用的な顧客管理ツールを、ステップバイステップで組み立てていきます。

顧客管理CLIアプリの全体像をイメージする

どんなことができるアプリにするか

まずは、機能をシンプルに絞り込みます。

  • 顧客を追加する(名前・メール・電話番号・メモ)
  • 顧客一覧を表示する
  • 顧客を検索する(名前の一部で検索)
  • 顧客情報を更新する
  • 顧客を削除する

これだけでも、立派な「顧客管理ツール」です。

操作はすべて CLI(コマンドライン) から行います。

  • 起動するとメニューが表示される
  • 数字を入力して操作を選ぶ
  • 必要な情報を聞かれたら入力する

という、落ち着いた対話型のアプリにしていきます。

データベース設計 ― customersテーブルを作る

顧客情報に必要なカラムを決める

顧客管理なので、最低限こんな項目が欲しくなります。

  • id:主キー(自動採番)
  • name:顧客名(必須)
  • email:メールアドレス(必須・重複なしにしてもよい)
  • phone:電話番号(任意)
  • note:メモ(任意)

SQLiteのテーブル定義はこんな感じになります。

CREATE TABLE IF NOT EXISTS customers (
    id     INTEGER PRIMARY KEY AUTOINCREMENT,
    name   TEXT NOT NULL,
    email  TEXT NOT NULL UNIQUE,
    phone  TEXT,
    note   TEXT
);

Pythonでテーブルを作る関数を書く

# day66_customer_cli.py
import sqlite3
from pathlib import Path


DB_NAME = "day66_customers.db"


def get_connection() -> sqlite3.Connection:
    """
    SQLiteデータベースに接続するための関数です。
    ファイルがなければ新しく作られます。
    """
    db_path = Path(DB_NAME)
    conn = sqlite3.connect(db_path)
    return conn


def init_db(conn: sqlite3.Connection) -> None:
    """
    customers テーブルを作成する関数です。
    すでに存在する場合は何もしません。
    """

    sql = """
    CREATE TABLE IF NOT EXISTS customers (
        id     INTEGER PRIMARY KEY AUTOINCREMENT,
        name   TEXT NOT NULL,
        email  TEXT NOT NULL UNIQUE,
        phone  TEXT,
        note   TEXT
    );
    """

    cur = conn.cursor()
    cur.execute(sql)
    conn.commit()
Python

ここまでで、「顧客情報をしまっておく箱」が準備できました。

顧客を追加する機能 ― INSERTをアプリの“入口”にする

顧客追加の関数を作る

def add_customer(conn: sqlite3.Connection, name: str, email: str, phone: str | None = None, note: str | None = None) -> None:
    """
    customers テーブルに新しい顧客を追加する関数です。
    1回の呼び出しで、1レコード(1人分)が追加されます。
    """

    print(f"[ADD] 顧客を追加します: name={name}, email={email}, phone={phone}, note={note}")

    sql = """
    INSERT INTO customers (name, email, phone, note)
    VALUES (?, ?, ?, ?);
    """

    cur = conn.cursor()
    cur.execute(sql, (name, email, phone, note))
    conn.commit()

    print("[ADD] 顧客の追加が完了しました。")
Python

CLIから入力を受け取る

def prompt_add_customer(conn: sqlite3.Connection) -> None:
    """
    CLIから顧客情報を入力してもらい、追加するための関数です。
    """

    print("=== 顧客追加 ===")
    name = input("名前: ").strip()
    email = input("メールアドレス: ").strip()
    phone = input("電話番号(任意): ").strip()
    note = input("メモ(任意): ").strip()

    # 空文字の場合は None にしておくと扱いやすいです。
    phone = phone or None
    note = note or None

    add_customer(conn, name, email, phone, note)
Python

ここでのポイントは、

  • input() でユーザーから情報を受け取る
  • .strip() で前後の空白を取り除く
  • 任意項目は、空なら None にしておく

という、CLIらしい素朴なやり取りです。

顧客一覧を表示する機能 ― SELECTで「今の状態」を眺める

全顧客を取得する関数

def list_customers(conn: sqlite3.Connection) -> list[tuple]:
    """
    customers テーブルから全顧客を取得する関数です。
    戻り値は、レコードごとのタプルのリストになります。
    """

    sql = """
    SELECT id, name, email, phone, note
    FROM customers
    ORDER BY id ASC;
    """

    cur = conn.cursor()
    cur.execute(sql)
    rows = cur.fetchall()
    return rows
Python

CLIで一覧を表示する

def show_customers(conn: sqlite3.Connection) -> None:
    """
    顧客一覧をCLIに表示する関数です。
    """

    print("=== 顧客一覧 ===")
    rows = list_customers(conn)

    if not rows:
        print("登録されている顧客はいません。")
        return

    for row in rows:
        customer_id, name, email, phone, note = row
        print("-" * 40)
        print(f"ID   : {customer_id}")
        print(f"名前 : {name}")
        print(f"メール: {email}")
        print(f"電話 : {phone or '(未登録)'}")
        print(f"メモ : {note or '(なし)'}")
    print("-" * 40)
Python

一覧表示は、アプリの「今の状態」を確認するための大事な窓です。 ここが見やすいと、ちょっとしたツールでも「ちゃんとした感」がぐっと増します。

顧客検索機能 ― WHEREで「名前の一部から探す」

名前の部分一致検索をする

def search_customers_by_name(conn: sqlite3.Connection, keyword: str) -> list[tuple]:
    """
    名前に keyword を含む顧客を検索する関数です。
    部分一致検索を行います。
    """

    sql = """
    SELECT id, name, email, phone, note
    FROM customers
    WHERE name LIKE ?
    ORDER BY id ASC;
    """

    # LIKE 用に、%keyword% の形にします。
    pattern = f"%{keyword}%"

    cur = conn.cursor()
    cur.execute(sql, (pattern,))
    rows = cur.fetchall()
    return rows
Python

CLIからキーワードを受け取る

def prompt_search_customer(conn: sqlite3.Connection) -> None:
    """
    名前のキーワードを入力してもらい、検索結果を表示する関数です。
    """

    print("=== 顧客検索(名前) ===")
    keyword = input("検索キーワード: ").strip()

    if not keyword:
        print("キーワードが空です。検索を中止します。")
        return

    rows = search_customers_by_name(conn, keyword)

    if not rows:
        print("該当する顧客は見つかりませんでした。")
        return

    print(f"{len(rows)} 件の顧客が見つかりました。")
    for row in rows:
        customer_id, name, email, phone, note = row
        print("-" * 40)
        print(f"ID   : {customer_id}")
        print(f"名前 : {name}")
        print(f"メール: {email}")
        print(f"電話 : {phone or '(未登録)'}")
        print(f"メモ : {note or '(なし)'}")
    print("-" * 40)
Python

検索機能が入ると、一気に「ツール感」が増します。 「名前の一部で探せる」というだけでも、使い勝手がかなり変わります。

顧客情報の更新機能 ― UPDATEで「間違いを直す」

特定IDの顧客を更新する

def update_customer(
    conn: sqlite3.Connection,
    customer_id: int,
    name: str | None = None,
    email: str | None = None,
    phone: str | None = None,
    note: str | None = None,
) -> None:
    """
    指定した ID の顧客情報を更新する関数です。
    渡された値が None の項目は更新しません。
    """

    # 動的に SET 句を組み立てます。
    fields = []
    params: list[str | int | None] = []

    if name is not None:
        fields.append("name = ?")
        params.append(name)

    if email is not None:
        fields.append("email = ?")
        params.append(email)

    if phone is not None:
        fields.append("phone = ?")
        params.append(phone)

    if note is not None:
        fields.append("note = ?")
        params.append(note)

    if not fields:
        print("[UPDATE] 更新する項目がありません。")
        return

    set_clause = ", ".join(fields)

    sql = f"""
    UPDATE customers
    SET {set_clause}
    WHERE id = ?;
    """

    params.append(customer_id)

    cur = conn.cursor()
    cur.execute(sql, params)
    conn.commit()

    print("[UPDATE] 顧客情報の更新が完了しました。")
Python

CLIで「どの項目を直すか」を聞く

def prompt_update_customer(conn: sqlite3.Connection) -> None:
    """
    顧客IDを指定して、更新したい項目だけを入力してもらう関数です。
    空の入力は「変更しない」とみなします。
    """

    print("=== 顧客情報更新 ===")
    try:
        customer_id = int(input("更新したい顧客のID: ").strip())
    except ValueError:
        print("IDは整数で入力してください。")
        return

    # 現在の情報を表示しておくと親切です。
    cur = conn.cursor()
    cur.execute(
        "SELECT id, name, email, phone, note FROM customers WHERE id = ?;",
        (customer_id,),
    )
    row = cur.fetchone()

    if row is None:
        print("指定されたIDの顧客は存在しません。")
        return

    _, current_name, current_email, current_phone, current_note = row

    print("現在の情報:")
    print(f"名前 : {current_name}")
    print(f"メール: {current_email}")
    print(f"電話 : {current_phone or '(未登録)'}")
    print(f"メモ : {current_note or '(なし)'}")

    print("変更したい項目だけ、新しい値を入力してください。")
    print("空のまま Enter を押すと、その項目は変更されません。")

    name = input("新しい名前(未変更なら空のまま): ").strip()
    email = input("新しいメール(未変更なら空のまま): ").strip()
    phone = input("新しい電話(未変更なら空のまま): ").strip()
    note = input("新しいメモ(未変更なら空のまま): ").strip()

    name = name or None
    email = email or None
    phone = phone or None
    note = note or None

    update_customer(conn, customer_id, name, email, phone, note)
Python

「間違えて登録してしまった」「メールアドレスが変わった」 そんなときに、更新機能があると安心感がぐっと増します。

顧客削除機能 ― DELETEで「もう使わないデータを片付ける」

特定IDの顧客を削除する

def delete_customer(conn: sqlite3.Connection, customer_id: int) -> None:
    """
    指定した ID の顧客を削除する関数です。
    """

    sql = "DELETE FROM customers WHERE id = ?;"

    cur = conn.cursor()
    cur.execute(sql, (customer_id,))
    conn.commit()

    print("[DELETE] 顧客の削除が完了しました。")
Python

CLIで削除を確認する

def prompt_delete_customer(conn: sqlite3.Connection) -> None:
    """
    顧客IDを指定して削除する前に、確認を行う関数です。
    """

    print("=== 顧客削除 ===")
    try:
        customer_id = int(input("削除したい顧客のID: ").strip())
    except ValueError:
        print("IDは整数で入力してください。")
        return

    cur = conn.cursor()
    cur.execute(
        "SELECT id, name, email FROM customers WHERE id = ?;",
        (customer_id,),
    )
    row = cur.fetchone()

    if row is None:
        print("指定されたIDの顧客は存在しません。")
        return

    _, name, email = row
    print(f"削除対象: ID={customer_id}, 名前={name}, メール={email}")
    confirm = input("本当に削除しますか? (y/N): ").strip().lower()

    if confirm == "y":
        delete_customer(conn, customer_id)
    else:
        print("削除をキャンセルしました。")
Python

削除は取り返しがつかない操作なので、 「本当に削除していいか?」 を一度確認するのが、優しさでもあり安全性でもあります。

メニューとメインループ ― CLIアプリとして完成させる

メニュー表示関数

def print_menu() -> None:
    """
    顧客管理CLIアプリのメニューを表示する関数です。
    """

    print("\n=== 顧客管理CLIメニュー ===")
    print("1. 顧客追加")
    print("2. 顧客一覧表示")
    print("3. 顧客検索(名前)")
    print("4. 顧客情報更新")
    print("5. 顧客削除")
    print("0. 終了")
Python

メイン関数でループを回す

def main() -> None:
    """
    顧客管理CLIアプリのエントリポイントです。
    メニューを表示し、ユーザーの選択に応じて処理を呼び分けます。
    """

    conn = get_connection()
    init_db(conn)

    print("顧客管理CLIアプリを起動しました。")

    while True:
        print_menu()
        choice = input("番号を選んでください: ").strip()

        if choice == "1":
            prompt_add_customer(conn)
        elif choice == "2":
            show_customers(conn)
        elif choice == "3":
            prompt_search_customer(conn)
        elif choice == "4":
            prompt_update_customer(conn)
        elif choice == "5":
            prompt_delete_customer(conn)
        elif choice == "0":
            print("アプリを終了します。")
            break
        else:
            print("不正な入力です。0〜5の番号を選んでください。")

    conn.close()


if __name__ == "__main__":
    main()
Python

これで、ひとつのファイル day66_customer_cli.py を実行すると、

  • データベースが初期化され
  • メニューが表示され
  • 顧客の追加・一覧・検索・更新・削除ができる

という、小さくて頼れる顧客管理CLIアプリ が完成します。

Day 66のまとめ ― 「学んだピースが、ひとつの作品にまとまる」感覚

今日のテーマは、

  • SQLiteでテーブルを設計する
  • Pythonから接続して、INSERT / SELECT / UPDATE / DELETE を行う
  • CLIでユーザーと対話しながら、顧客情報を管理する

という、これまで学んできた要素を「ひとつのアプリ」にまとめることでした。

コードの量は少し増えましたが、 やっていることは、Day 61〜65で触れてきた内容の組み合わせです。

  • テーブル設計(主キー・UNIQUE・NOT NULL)
  • SELECT / WHERE / ORDER BY
  • INSERT / UPDATE / DELETE
  • プレースホルダで安全に値を渡す
  • CLIで input() を使って対話する

それぞれのピースが、 「顧客管理CLIアプリ」という具体的な形 に収まったことで、 「自分でもこういうツールが作れるんだ」という実感が、少しずつ湧いてきているはずです。

タイトルとURLをコピーしました