Pythonで簡単DB

# pythonでsqlite3データベースを簡単に使う

SQLとかわかんないよみたいな方だってデータベースに触れたら世界が変わるかも知れない。わかんないけど。
ほとんどの場合ざっくりと簡単なクエリ発行で事足りる場合が多いので、SQLに詳しい方だって多分楽できるかも。

## DBクラスとDBwrapperクラス

ほぼ素に近い状態でsqliteを使うDBクラスと、そのDBクラスを継承して簡単に使えるファンクションを追加したのがDBwrapperクラス。
DBwrapperクラスはDBクラスのファンクションを全部使えるのでとりあえずDBwrapperクラスを取り込んで使えば便利。

たとえば dict型でデータを作って **set** とか読んでやればDBにデータを挿入・更新できたり **get** をforで回してやれば1行づつデータが取り出せる。
データの件数も **count** で取り出せるぞ、手軽だね。

詳しくは以下のコードの **デモ** を見てほしい。
あと、テーブル作成を簡単にするファンクションは思いつきつつ気力が無くなったので必要があれば色々考えて作ってみてほしい。（SQLを勉強したほうが良い結果でそうだけどね）

# コード

```python
import sqlite3

class DB:
    def __init__(self, filePath=None):
        if filePath != None:
            self.filePath = filePath

    def open(self, filePath=None):
        if filePath != None:
            self.filePath = filePath
        self.connection = sqlite3.connect(self.filePath)
        self.cursor = self.connection.cursor()

    def close(self):
        self.cursor.close()
        self.connection.close()

    def fetch(self, sql):
        for row in self.cursor.execute(sql):
            yield row

    def query(self, sql):
        self.cursor.execute(sql)

    def commit(self):
        self.connection.commit()

    def rollback(self):
        self.connection.rollback()

    def __enter__(self):
        self.open()
        return self

    def __exit__(self, exctype, excvalue, traceback):
        self.close()


class DBwrapper(DB):

    def set(self, tablename, args={}):
        if len(args) == 0:
            return False
        cols = list(args.keys())
        vals = []
        for col in cols:
            if type(args[col]) == str:
                vals.append("'%s'" % args[col])
            else:
                vals.append(str(args[col]))
        columns = ",".join(cols)
        values = ",".join(vals)
        sql = f"replace into {tablename} ({columns}) values ({values})"
        self.query(sql)
        return True

    def get(self, tablename, args={}):
        columns = self._getColumns(tablename)
        columnNames = ",".join(columns.keys())
        if len(args) > 0:
            wh = self._keyValue(args)
            sql = f"select {columnNames} from {tablename} where {' and '.join(wh)}"
        else:
            sql = f"select {columnNames} from {tablename}"
        for row in self.fetch(sql):
            buf = {}
            for idx, col in enumerate(columns):
                buf[col] = row[idx]
            yield buf

    def count(self, tablename, args={}):
        if len(args) > 0:
            wh = self._keyValue(args)
            sql = f"select count(*) from {tablename} where {' and '.join(wh)}"
        else:
            sql = f"select count(*) from {tablename}"
        row = self.fetch(sql)
        return row.__next__()[0]

    def _getColumns(self, tablename):
        sql = f"pragma table_info('{tablename}')"
        columns = {x[1]: x[2] for x in self.fetch(sql)}
        return columns

    def _keyValue(self, args={}):
        keys = list(args.keys())
        wh = []
        for key in keys:
            if type(args[key]) == str:
                wh.append("%s = '%s'" % (key, args[key]))
            else:
                wh.append("%s = %s" % (key, args[key]))
        return wh


"""
ここからデモ
"""

if __name__ == "__main__":

    with DBwrapper("hello.db") as db:

        """ テーブルの作成 """
        sql = """
        CREATE TABLE if not exists names
        (
            "id" INTEGER,
            "name" TEXT,
            "age" INTEGER,
            PRIMARY KEY("id" AUTOINCREMENT)
        );
        """
        db.query(sql)

        """
        テーブル作成や込み入ったクエリの発行には queryやfetchを使う。
        ほとんどの場合はwrapperで用意したgetとsetで事足りる（かも）
        """
        # sql = "insert into names ('name') values ('Python')"
        # db.query(sql)
        #
        # sql = "insert into names ('name') values ('Sqlite3')"
        # db.query(sql)
        #
        # for row in db.fetch("select * from names"):
        #     print(row)

        """ テーブルにデータを挿入 """
        dat = {"id": 1, "name" : "json", "age": 4}
        db.set("names", dat)

        dat = {"id": 2, "name": "python", "age": 0}
        db.set("names", dat)

        """ 以下はnameが指定されていないのでnullになってしまうことに注意 """
        # dat = {"id": 2, "age": 30}
        # db.set("names", dat)

        """
        プライマリキーでデータを参照してデータを更新する
        （※正しくは削除と挿入）
        """
        dat = {"id": 2, "name": "python", "age": 30}
        db.set("names", dat)

        """ dict型で全件取得 """
        for row in db.get("names"):
            print(row)

        print("---")

        """ 条件を指定してdict型でデータ取得する """
        dat = {"name": "python"}
        for row in db.get("names", dat):
            print(row)

        """ テーブルのデータ件数を取得する """
        print(db.count("names"))

        """ コミットとかロールバック """
        #db.commit()
        db.rollback()
```

例のごとく簡易版ではあるけれど十分使えると思います。
何か複雑そうに見えるかもしれないけど本当に簡単につかえるのでコピペして遊んでみてね。