🐷

Pythonでsqlite3を実践!!

2023/04/26に公開
test.py
import sqlite3


def open_db():
    """
    DBを開く。ない場合は新規で作成
    """
    dbname = 'TEST.db'
    conn = sqlite3.connect(dbname)
    return conn

def setup_db(conn):
    """
    テーブルを作成
    """
    cur = conn.cursor()
    cur.execute('CREATE TABLE account(id INTEGER, name STRING, mail STRING)')
    cur.execute('INSERT INTO account VALUES(0, "太郎", "xxxxxxxx")')
    conn.commit()


def getAccountRecord(conn):
    """
    クエリを実行する
    """
    cur = conn.cursor()
    cur.execute("SELECT * FROM account")
    for x in cur.fetchall():
        print(x)

connect = open_db()
setup_db(connect)
getAccountRecord(connect)
connect.close()

上記のコードはDBの作成、テーブルの作成、クエリの実行を一連で行います。
実行するとカレントディレクトリに、「TEST.db」ファイルが作成されていると思います。

CREATE TABLE IF NOT EXISTS ...

もう一度、実行すると例外が発生するはずです。

sqlite3.OperationalError: table account already exists

テーブルをすでに作成しているからですね。'CREATE TABLE IF NOT EXISTS'を活用すると良いですね。

def setup_db(conn):
    """
    テーブルを作成
    """
    cur = conn.cursor()
    cur.execute('CREATE TABLE IF NOT EXISTS account(id INTEGER, name STRING, mail STRING)')
    cur.execute('INSERT INTO account VALUES(0, "太郎", "xxxxxxxx")')
    conn.commit()

上記のように書き換えると、テーブルがあっても例外が発生しなくなります。

プログラムでデータを管理する。

アプリケーションを起動するごとに、DBを構築したいとしましょう。
このままだと実行するたびにエラーは発生しなくなりましたが、レコードが追加されていきます。

(0, '太郎', 'xxxxxxxx')
(0, '太郎', 'xxxxxxxx')
(0, '太郎', 'xxxxxxxx')
...

そこでDROP TABLE IF EXISTS..でテーブルを一度リセットするコードにしてみます。

def setup_db(conn):
    """
    テーブルを作成
    """
    cur = conn.cursor()
    cur.execute('DROP TABLE IF EXISTS account')
    cur.execute('CREATE TABLE IF NOT EXISTS account(id INTEGER, name STRING, mail STRING)')
    cur.execute('INSERT INTO account VALUES(0, "太郎", "xxxxxxxx")')
    conn.commit()

クラス化してみよう。

上記の内容をクラス化してみましょう。

import sqlite3

class DbOperator:

    def __init__(self):
        self.dbname = 'TEST.db'
        self.conn = sqlite3.connect(self.dbname)
        self._set_up()

    def _set_up(self):
        cur = self.conn.cursor()
        cur.execute('DROP TABLE IF EXISTS account')
        cur.execute('CREATE TABLE IF NOT EXISTS account(id INTEGER, name STRING, mail STRING)')
        cur.execute('INSERT INTO account VALUES(0, "太郎", "xxxxxxxx")')
        self.conn.commit()

    def exe_query(self, query:str):
        cur = self.conn.cursor()
        cur.execute(query)
        for x in cur.fetchall():
            print(x)

    def close(self):
        self.conn.close()

db_operator =  DbOperator()
db_operator.exe_query("SELECT * FROM account")
db_operator.close()

DBのセットアップのクラスが作成できました。テストでのDBとして使えそうです。(インメモリのDBのほうが効率は良さそうですが..)

Discussion