SQLiteはデータベースの一種で簡単に扱うことができます。MySQL等のRDBMSと比較すると機能は限定的ですが、圧倒的なスピードが特徴的で、大量データに対する分析で活用することもできます。Pythonには標準ライブラリで軽量DBのsqlite3を使用するモジュールが提供されています。このページでは、そのsqlite3モジュールについて解説します。
Contents
PythonとSQLite3
SQLiteは冒頭で記述したとおり非常に軽量なデータベースの一種です。現在バージョン3であるため、SQLite3と記述されることもあります。SQLiteの最大のメリットはサーバープロセスを起動する必要がなく、ファイルで永続化することが可能です。また、オンメモリで動作させることもでき、気軽にRDBを利用することが可能です。Pythonは標準ライブラリが用意されており、簡単にSQLite3にアクセスすることができます。
接続とSQLの実行
sqlite3のインポート
まずは接続とSQLの実行方法について解説します。使用するモジュールはsqlite3という名称で、標準ライブラリのためインストールは不要です。以下でインポートすることができます。
import sqlite3
接続
接続は以下のように記述します。
指定したDBファイルが存在しない場合は自動で作成してくれるため、高い可搬性を実現することができます。また、特別な名前である :memory: を使うとRAM上にデータベース、いわゆるインメモリ(若しくはオンメモリ)で作ることもできます。
カーソルの取得とSQLの実行
コネクションからカーソルを取得し、excecuteメソッドでSQLを実行します。SELECT文の結果取得については後述します。
c.execute(
テーブル作成と型
上のexecuteの中のSQL文はCREATE文のようなDDLを指定することが可能です。テーブルを作成する場合、例えば以下のようにCREATE文を実行します。
c.execute('CREATE TABLE articles (id int, title varchar(1024), body text, created datetime)')
なお、SQLiteとPythonとの型の対応は以下のようになります。
| Python の型 | SQLite の型 |
|---|---|
| None | NULL |
| int | INTEGER |
| float | REAL |
| str | TEXT |
| bytes | BLOB |
CREATE文とINSERT文のサンプル
それでは接続からSQL実行までのサンプルです。以下のサンプルはカレントディレクトリ直下にexample.dbというdbファイルを作成し、CREATE文でテーブルを作成後、INSERT文でデータを挿入してみます。
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,'今朝のおかず','魚を食べました','2020-02-01 00:00:00')")
c.execute("INSERT INTO articles VALUES (2,'今日のお昼ごはん','カレーを食べました','2020-02-02 00:00:00')")
c.execute("INSERT INTO articles VALUES (3,'今夜の夕食','夕食はハンバーグでした','2020-02-03 00:00:00')")
# コミット
conn.commit()
# コネクションをクローズ
conn.close()
実際、上のサンプルでテーブル作成とデータ挿入がされたことを以下のsqlite3のコマンドで確認することができます。お使いの環境に適宜sqlite3をインストールしてください。
$ sqlite3 example.db .tables select * from articles;
SELECT文の実行
カーソルを取得後はexecuteメソッドでSELECT文を実行することができます。実行結果をカーソルから取得する方法は大きく分けると3つあります。
- カーソルをイテレータ (iterator) として扱う
- fetchallで結果リストを取得する
- fetchoneで1件ずつ取得する
いずれも結果レコードはタプル形式で取得できます。サンプルで確認してみましょう。
import sqlite3
# DBに接続する。なければDBを作成する。
conn = sqlite3.connect('example.db')
# カーソルを取得する
c = conn.cursor()
# 1. カーソルをイテレータ (iterator) として扱う
c.execute('select * from articles')
for row in c:
# rowオブジェクトでデータが取得できる。タプル型の結果が取得
print(row)
# 2. fetchallで結果リストを取得する
c.execute('select * from articles')
for row in c.fetchall():
print(row)
# 3. fetchoneで1件ずつ取得する
c.execute('select * from articles')
print(c.fetchone()) # 1レコード目が取得
print(c.fetchone()) # 2レコード目が取得
# コネクションをクローズする
conn.close()
なお、fetchoneを実行した際、レコードがない場合はNoneが返されます。
トランザクション
分離レベルの指定
SQLiteは軽量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が指定できます。
TIPS
最後にいくつかの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はsqlite_masterにメタ情報が格納されています。where条件にtype='table'を指定することでテーブル一覧を取得することが可能です。
c.execute("select * from sqlite_master where type='table'")
for row in c.fetchall():
print(row)
sqlite3.Rowによるカラム名による取得
sqlite3.Rowを使用するとSELECT結果をカラム名で指定して取得することができます。コネクションオブジェクトのrow_factoryにsqlite3.Rowを設定します。
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']) # カラム名でアクセスすることができる。n
# コネクションをクローズする
conn.close()
