pythonでSQLite使ってみた

はじめに

今作ってるPythonのGUIアプリでデータベースでデータ管理したいなと思ったので、

SQLite使ってみました。

実際のコード

実際に書いてみたコードはこちら。だいぶ雑ですが。

import sqlite3
import os

conn = sqlite3.connect('caption.db')

table_name = 'text_file_info'

def is_exist_db():
    return os.path.isfile('caption.db')

# fileinfoテーブルの存在有無確認
def is_exist_fileinfo_table():
    c = conn.cursor()
    c.execute(r"SELECT COUNT(*) FROM sqlite_master WHERE TYPE='table'")
    lis = c.fetchall()
    # テーブルが作成されているかを確認し、作成されていなければ新規作成
    if lis[0][0] == 0:
        initialize()

# テーブルの初期化(とりあえず作成だけ)
def initialize():
    c = conn.cursor()
    c.execute('CREATE TABLE ' + table_name +
             '''(no INTEGER PRIMARY KEY AUTOINCREMENT, 
                file_name text, 
                file_path text, 
                file_update_date text,
                read_word_count integer, 
                all_word_count integer)''')
    conn.commit()

# 該当ファイルデータの存在有無確認(戻り値は)
def is_exist_file_info(file_name, file_path):
    c = conn.cursor()
    param = [file_name, file_path]
    c.execute(r"SELECT COUNT(*) FROM text_file_info WHERE file_name=? AND file_path=?", param)
    lis = c.fetchall()

    data_no = 0
    print(lis)
    return not (lis[0][0] == 0)

# ファイルデータを登録する
def insert_file_info(file_name, file_path, file_update_date, all_word_count):
    try:
        query = "insert into text_file_info (file_name, file_path, file_update_date, read_word_count, all_word_count) values( ?, ?, ?, ?, ? )"
        param = [file_name, file_path, file_update_date, 1, all_word_count]
        conn.execute(query, param)

    except sqlite3.Error as e:
        print("error",e.args[0])
        return
    conn.commit()

    return get_file_info(file_name, file_path)

# ワードカウントを更新する
def update_wordcount(no, read_word_count):
    try:
        query = "update text_file_info set read_word_count=? where no = ?"
        param = [read_word_count, no]
        conn.execute(query, param)

    except sqlite3.Error as e:
        print("error",e.args[0])
        return
    conn.commit()

# ファイルパスが一致するデータを取得する
def get_file_info(file_name, file_path):
    try:
        c = conn.cursor()
        param = [file_name, file_path]
        c.execute(r"SELECT * FROM text_file_info WHERE file_name=? AND file_path=?", param)
        lis = c.fetchall()
    
        info_data = lis[0]
        print(info_data)
    except sqlite3.Error as e:
        print("error",e.args[0])
        return -1

    return info_data


def close():
    conn.close()

SQLiteをPythonで使うためにはsqlite3をインポートします。

import sqlite3

使うためにはconnect()メソッドを使ってdbファイルに接続します。

もしdbファイルがなかった場合は自動的に新規作成されます。

テーブル作るためには以下のソース。

    table_name = 'text_file_info'
    c = conn.cursor()
    c.execute('CREATE TABLE ' + table_name +
             '''(no INTEGER PRIMARY KEY AUTOINCREMENT, 
                file_name text, 
                file_path text, 
                file_update_date text,
                read_word_count integer, 
                all_word_count integer)''')
    conn.commit()

テーブル作るところは通常のSQLiteのテーブル作る構文をexecute()メソッドで実行してるだけです。

ここではnoというカラムを主キー、かつ自動で採番して欲しかったので、PRIMARY KEYAUTOINCREMENTをオプションとして使ってます。

ちなみに文字列をシングルクオート3つで囲んでいるのは改行で分かりやすいようにしたいと思って使ってます。

INSERTはこちら。

query = "insert into text_file_info (file_name, file_path, file_update_date, read_word_count, all_word_count) values( ?, ?, ?, ?, ? )"
        param = [file_name, file_path, file_update_date, 1, all_word_count]
        conn.execute(query, param)

?の記載は構文の中で記載しておいてexecute()メソッドを実行する際にlistにまとめたパラメータを渡してあげると置き換えてくれます。

今回の場合はparam = [file_name, file_path, file_update_date, 1, all_word_count]という形でパラメータのリストを作ってあげて渡してます。

勝手に置き換えてくれるのは便利ですね。

UPDATEはこちら。

        query = "update text_file_info set read_word_count=? where no = ?"
        param = [read_word_count, no]
        conn.execute(query, param)

こちらも基本はSQLiteの構文と同じでINSERTと同じように?で値を置き換えています。

実際に書いてる時、そもそものSQLiteの構文結構忘れてて触ってないとダメだなと思いました。

同じようなこと半年前ぐらいに組んでるんですけどね。

SELECT文はこちら。

        c = conn.cursor()
        param = [file_name, file_path]
        c.execute(r"SELECT * FROM text_file_info WHERE file_name=? AND file_path=?", param)
        lis = c.fetchall()
    
        info_data = lis[0]

書きっぷりは基本的に他のINSERT, UPDATE文とあまり変わらないですね。

ちょっと違うところとしてはSELECT文なのでデータを取得したいのでexecute()メソッドをした後にfetchall()メソッドでデータを取得してます。

fetchallは複数データをまとめて持ってくるんですが、今回はデータの都合上一件しか持ってこない仕様なので処理ではインデックス0番目のデータを無理やり持ってきてます。

fetchoneとかでもいいか?と思いましたがとりあえず試してみるかと思って一旦fetchall使ってます。

たぶん後で書き換えます。

CRUDの中でDELETE文はまだ書いてないですが、必要になる処理がなかったので今のところ書いてません。

こちらも後で処理追加しておきます。ユーザー操作から使う機会はないですが。

最後に

とりあえず実装してみた処理をざっと書いてみました。

DB処理って使おうとして処理書くまでは億劫ですが、実際に書いてみたら楽しい。

今回のは割とハードコーディングで書いてしまったのですが、

もう少し書き方ないんですかね、ありそうな気はしますけど。

ORマッパーみたいなのがないかとかも合わせて使いやすくしておきたい。

割と自分でDB処理書きたいと思う機会自体は多いですが、

諸々めんどくさくなってしまうのである程度テンプレート化できたらいいな。

とりあえず今日はこの辺で。

それではー

コメント

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