LoginSignup
14
12

More than 3 years have passed since last update.

[Python3][SQLite3]レコードを辞書型(dict型)で取得する簡単な方法

Last updated at Posted at 2020-01-08

pythonからSELECT文でレコードを1行取得すると、タプル(tuple型)(例(1, 'ABC'))で返ってくる。それをカラム名をkeyとした辞書型(dict型)(例{'id': 1, 'name': ABC})で取得する方法をまとめる。

具体的には、sqlite3のConnection オブジェクトのrow_factory属性を変更することで簡単に実現できる。

dict型で取得することで、keyにカラム名を指定して取得したレコードから要素を取り出すことができるようになる。

そもそも辞書型とは

とっても便利なPythonの辞書型について覚え書き

環境

  • Python 3.7.4

サンプルプログラムの動作

INTEGER型の'id'と、TEXT型の'name'という2つのカラムを持つテーブルに格納された下表の2件のデータを{'id': 1, 'name': '加藤'}{'id': 2, 'name': '佐藤'}のようなdict型で取得する。

id name
1 佐藤
2 加藤

準備: テーブルの作成

テーブルの内容確認のためにSELECT文を発行して1行取得しているが、tuple型で返ってくる。

create_table.py
import sqlite3

dbname = 'database.db'

connection = sqlite3.connect(dbname)
cursor = connection.cursor()

cursor.execute("CREATE TABLE sample (id INTEGER, name TEXT)")
cursor.execute("INSERT INTO sample VALUES (1, '加藤')")
cursor.execute("INSERT INTO sample VALUES (2, '佐藤')")
connection.commit()

#テーブルの内容確認
cursor.execute("SELECT * FROM sample")

# レコードを1行取得
print(cursor.fetchone()) #tuple型
#(1, '加藤')

# レコードを1行取得
print(cursor.fetchone()) #tuple型
#(2, '佐藤')

connection.close()

dict型でのレコード取得

sqlite3のConnection オブジェクトのrow_factory属性を変更することで、SELECT文を発行して1行取得すると、dict型が返ってくる。

select_table.py
# sqlite3 標準モジュールをインポート
import sqlite3

# データベースファイルのパス
dbpath = 'database.db'


# dict_factoryの定義
def dict_factory(cursor, row):
   d = {}
   for idx, col in enumerate(cursor.description):
       d[col[0]] = row[idx]
   return d


if __name__ == "__main__": 
    # データベース接続
    con = sqlite3.connect(dbpath)

    # row_factoryの変更(dict_factoryに変更)
    con.row_factory = dict_factory

    # カーソル生成
    cur = con.cursor()
    # SETECT文の発行
    cur.execute("SELECT * FROM sample")

    # レコードを1行取得
    print(cur.fetchone()) #dict型
    #{'id': 1, 'name': '加藤'} 

    # レコードを1行取得
    print(cur.fetchone()) #dict型
    #{'id': 2, 'name': '佐藤'} 

    # 接続を閉じる
    con.close()

row_factory属性の変更

sqlite3のConnection オブジェクトのdict_factory関数を定義して、row_factoryを変更することで、取得される1行の形式を変更できる。

dict_factory関数に記述されたcursorオブジェクトのdescription属性は、読み取り専用で、最後に発行されたクエリの結果のカラム名がタプルとして格納されている。また、enumerate関数によりタプルのインデックス番号と要素が同時に取得され、dict型の戻り値が生成されている。

辞書型で取得できると何が変わるのか?

tuple型で取得されると、取得されたデータにカラム名が含まれないので、取得したレコードから要素を取り出す際に、インデックス番号を指定することになるので、取り出される要素の順番を意識しておく必要がある。

# tuple型のデータからidの要素(value)を取り出す。
print(cursor.fetchone()[0]) #インデックス番号を指定
#1

dict型で取得すると、カラム名を含めて取得できるので、keyにカラム名を指定して取得したレコードから要素を取り出すことができるようになる。

# dict型のデータからidの要素(value)を取り出す。
print(cursor.fetchone()['id']) #keyにカラム名を指定
#1

蛇足: keyとvalueのタプルから辞書を作成

レコードの1行をtupule型で取得した後に、dict型に変換することはできるが、カラム数が増えてくるとkeyのタプルを作るのが面倒くさくなる。

keys = ('id', 'name')
values = (1, "ABC")

dic = dict(zip(keys, values)) 
print(dic)
#{'id': 1, 'name': 'ABC'}

参考

sqlite3 --- SQLite データベースに対する DB-API 2.0 インタフェース

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12