Python学習講座

PythonエンジニアによるPython3学習支援サイト

DB操作

sqlite3

2017/04/11


sqlite3はMySQL等と比較すると機能は限定されますが、圧倒的なスピードが特徴的で、大量データに対する分析で活用することもできます。pythonには標準ライブラリで軽量DBのsqlite3を使用するモジュールが提供されています。このページでは、そのsqlite3モジュールについて学習します。

接続とSQLの実行

まずはサンプルから見てみましょう。

import sqlite3

# 接続。なければDBを作成する。
conn = sqlite3.connect('example.db')

# カーソルを取得
c = conn.cursor()

# テーブルを作成
c.execute('CREATE TABLE articles  (id int, title varchar(1024), body text, created datetime)')

# Insert実行
c.execute("INSERT INTO articles VALUES (1,'今日のおかず','今日のおかずは魚でした','2018-12-01 00:00:00')")

# コミット
conn.commit()

# コネクションをクローズ
conn.close()

接続にはconnectメソッドにDBファイル名を使用します。指定したDBファイルが存在しない場合は自動で作成してくれるため、高い可搬性を実現することができます。また、特別な名前である :memory: を使うとRAM上にデータベースを作ることもできます。カーソルを取得後はexecuteメソッドでSQL文を実行することが可能です。

select文の実行

上のコードで実行したとおり、カーソルを取得後はexecuteメソッドでselect文も実行することができます。実行後の結果の取得方法は大きく分けると3つあります。サンプルで確認してみましょう。

import sqlite3

# DBに接続する。なければDBを作成する。
conn = sqlite3.connect('example.db')

# カーソルオブジェクトを取得する
c = conn.cursor()

# 1. カーソルをイテレータ (iterator) として扱う
for row in c.execute('select * from articles'):
    # rowオブジェクトでデータが取得できる。タプルライクなオブジェクトが取得できる。
    print(row)

# 2. カーソルの fetchone() メソッドを呼んで一致した内の一行を取得する
c.execute('select * from articles')
print(c.fetchone()) # 1レコード目が取得
print(c.fetchone()) # 2レコード目が取得


# 3. fetchall() メソッドを呼んで一致した全ての行のリストとして受け取る
c.execute('select * from articles')
for row in c.fetchall():
    print(row)

# コネクションをクローズする
conn.close()

fetchoneを実行した際、レコードがない場合はNoneが返されます。

トランザクション

分離レベルを指定する

sqlite3は軽量DBとはいえ、分離レベルを指定することができます。デフォルトではトランザクションが有効になっていますが、auto commitを使用する場合はコネクションオブジェクトのisolation_levelをNoneに設定します。なお、インスタンス生成時に引数で指定することも可能です。

# auto commitを有効にする

# コネクション生成時に指定する場合
conn = sqlite3.connect(dbpath, isolation_level=None)

# 生成後に指定する場合
conn.isolation_level = None

ロールバック

ロールバックする際はrollbackメソッドを使用します。

conn.rollback()

auto commit以外にはDEFERRED、IMMEDIATE、EXCLUSIVEが指定できます。

型の対応関係

sqliteとpythonとの型の対応は以下のようになります。

Python の型 SQLite の型
None NULL
int INTEGER
float REAL
str TEXT
bytes BLOB

TIPS

テーブルの有無を確認する

さて、このページの最初のコードですが、2回め以降はcreate文が、既に存在するテーブルとバッティングしてエラーが発生してしまいます。以下のようにselect文と組み合わせると、テーブルの存在判定をすることができます。

# テーブルを作成
c.execute("SELECT * FROM sqlite_master WHERE type='table' and name='articles'")
if not c.fetchone():
    c.execute('CREATE TABLE articles  (id int, title varchar(1024), body text, created datetime)')

sqlite3.Rowによるカラム名による取得

sqlite3.Rowを使用すると、select結果をカラム名で指定して取得することができます。コネクションオブジェクトのrow_factoryにsqlite3.Rowを設定します。

import sqlite3

import sqlite3
 
# DBに接続する。なければDBを作成する。
conn = sqlite3.connect('example.db')
conn.row_factory = sqlite3.Row # row_factoryにsqlite3.Rowを設定

# カーソルオブジェクトを取得する
c = conn.cursor()

c.execute('select * from articles')
for row in c:
    print(row['id']) # カラム名でアクセスすることができる。
 
# コネクションをクローズする
conn.close()

-DB操作
-