前回は、DBやRDBの基本を勉強しました。
今回はいよいよ、PythonからDBを活用していきましょう。
事前準備
sqlalchemyのインストール
$ pip install sqlalchemy
データベースの準備
データベースとの接続
db.py
を作成し、以下の内容を記述します。
from sqlalchemy import create_engine, MetaData
engine = create_engine('sqlite:///db.sqlite3', echo=True)
metadata = MetaData()
metadata.bind = engine
一行づつ解説していきます。
engine = create_engine('sqlite:///db.sqlite3', echo=True)
DBと接続するためのオブジェクトを作成します。
create_engine
の第一引数には、接続先DBのURLを指定します。DBのURLが何かについては詳しく説明しませんが、sqliteの場合はsqlite:///ファイル名
と指定すれば大丈夫です。
また、create_engine
にecho=True
を指定することで、ログが出力されるようになります。デバッグ等に役立つので指定しておくとよいでしょう。
原則として接続先のDBは予め作成する必要がありますが、sqliteでは接続先のDBが存在しない場合は自動で作成されます。
matadata = MetaData()
メタデータを作成します。
メタデータにはテーブルのスキーマ等が格納されるのですが、よくわからなければ「よくわからないけどDBのデータが入ってる」程度の認識で大丈夫です。
metadata.bind = engine
メタデータとDBを結びつけます。
テーブルの定義
ここでは、name
カラムとkcal
カラムを持ったmenus
テーブルを作成します。
db.pyを以下のように編集してください。
# テーブル定義用のクラスを追加でインポート
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
engine = create_engine('sqlite:///db.sqlite3', echo=True)
metadata = MetaData()
metadata.bind = engine
# menuテーブルの定義
menus = Table(
'menus', metadata,
Column('id', Integer, primary_key=True),
Column('name', String),
Column('kcal', Integer)
)
Table
の第一引数にはテーブル名を、第二引数にはメタデータを指定します。それ以降は、カラムを自由に指定することができます。
また、Column
の第一引数にはカラム名を、第二引数にはカラム型を設定します。また、id
カラムは主キーに設定しています。
テーブルの作成
ここまでで、テーブルの定義までは完了しましたが、まだテーブルは作成されていません。
インタラクティブシェルを起動して、以下のようにテーブルを作成しましょう。
>>> import db
>>> db.metadata.create_all()
発展: メタデータの意義
ここまでで、あまり説明できずにいたメタデータの意義がようやく見えてきます。metadataはテーブルの構造とengine
の両方を持っているので、テーブルを作成することができるのです。
もし、この時点でmetadata
とengine
が紐付けられていないなら、次のように明示的に指定する必要があります。
>>> import db
>>> db.metadata.create_all(engine)
また、テーブルの作成だけでなく、今後DBを操作する際にもやや面倒になるため、metadata
とengine
は予め結びつけておくことをおすすめします。
まとめ
- DBを使用するためには、DBとの接続・テーブルの定義・テーブルの作成を行う必要がある。
- メタデータはテーブルの情報を保持する。
やや難しかったかもしれませんが、DBを使用するための準備はこれで完了です。もしここまでの内容がよくわかっていなくても、次の内容に直ちに支障はありません。しかし、理解しておくべき内容なので、しばらく経ってから改めて読み返してみてください。
DBの活用
データの作成
データを作成する操作を、RDBMSではinsertと呼びます。作成(create)ではなく挿入(insert)であることに注意してください。これは、新しいデータを作成するというのは、テーブルに新しい行を挿入することだと考えると覚えやすいかもしれません。
sqlalchemyでは、insert
は以下のように実行します。
>>> import db
>>> db.menus.insert().execute(name='カレーメシ', kcal=500)
insert
を呼び出したあとに更にexecute
を呼び出していることに注意してください。execute
を呼び出すまでは操作が実行されることはありません。
これは、他の操作についても同様です。DBに対する操作は、原則としてexecute
を呼び出すまでは実行されません。
データの取得
データを取得するには、select
を使用します。
まずは、以下のコードを実行してみてください。
>>> import db
>>> db.menus.select().execute().fetchall()
[(1, 'カレーメシ', 500)]
insert
と同様に、execute
を呼び出すまではデータは取得されません。また、execute
の結果に対して更にfetchall
を呼び出していることに注意してください。
なお、返り値はタプルのリストのように見えますが、そうではありません。res[0][0]
というように、タプルのように扱うこともできますが、res[0]['id']
の用に、カラム名で取得することも可能です。
また、全データを取得するだけでなく、where
を利用して取得するデータを絞り込んだり、order_by
を使用してソートしたり、limit
を使用して取得するデータの件数を制限することもできます。
例えば、以下のコードでは「カロリーが100kcal未満の献立を5件まで取得してカロリー順にソートする」ことができます。
>>> import db
>>> db.menus.select().where(db.menus.c.kcal < 100).order_by('kcal').limit(5).execute().fetchall()
このような絞り込みは、データの更新や削除でも同様です。
データの更新
update
を使用します。基本はinsert
と同じですが絞り込みを行わない場合は全データが対象になることに注意してください。
以下のコードは、id
が1のデータのkcal
を1000に更新します。
>>> import db
>>> db.menus.update().where(db.menus.c.id == 1).execute(kcal=1000)
データの削除
delete
を使用します。基本は、insert
、update
と同様です。
以下のコードは、kcal
が1000より大きいデータをすべて削除します。
>>> import db
>>> db.menus.delete().where(db.menus.c.kcal > 1000).execute()
まとめ
- DBに対する操作は、
execute
を呼び出すまでは実行されない。 - select, update, deleteでは、データを絞り込むことができる。絞り込みを行わない場合はすべてのデータが対象になる。
前半に引き続き、やや難し目の内容でした。全部を理解できていなくても問題ありません。簡易的なリファレンスとしても活用できるので、迷ったら再確認しましょう。
今回のまとめ
今回は、前回に比べて難し目の内容でした。一度で理解できなくても問題ありません。また、理解したつもりになっていても、実際にコードを書こうとするとどう書けばよいかわからなくなることもあるので、そのようなときは改めて読み返してみましょう。