Más contenido relacionado La actualidad más candente (20) Similar a PlaySQLAlchemy: SQLAlchemy入門 (20) PlaySQLAlchemy: SQLAlchemy入門2. Yasushi Masuda PhD
( @whosaysni )
Tech team, Core IT grp. IT Dept.
MonotaRO Co., LTD.
Pythonista since 2001 (2.0~)
• elaphe (barcode library)
• oikami.py (老神.py)
• PyCon JP founder
翻訳もろもろ
15. 準備
sakila DB SQLite版 http://bit.ly/2fdeeft
https://github.com/jOOQ/jOOQ/jOOQ-examples/Sakila/sqlite-sakila-db/sqlite-sakila.sq
スキーマのドキュメントは下記
https://dev.mysql.com/doc/sakila/en/sakila-structure-tables.html
(上記のサイトのSQLiteデータベースバイナリは壊れているので、以下から取得してください)
https://github.com/wallymathieu/sakila-sample-database-ports/blob/master/sqlite-sakila-db/sqlite-sakila.sq
33. ここまでのまとめ
• create_engine() でエンジンを作れる
• engine.execute(query, *parameters) でクエリを実行
• 実行結果はResultProxyオブジェクト
アトリビュート、配列、辞書でアクセスできる
result.fetchall() や list(result) で一括取得もできる
• engine.connect().begin() でトランザクションを作れる
begin() でトランザクション接続を開ける
36. 俺の考えたさいきょうの...
• SELECT foo, bar, baz ... が
select(foo, bar, baz ...)
みたいに書ければ便利じゃない?
• WHERE foo='blue' AND bar=42 が
where(foo='blue', bar=42) みたいに書けないかな?
• t = table('mytable', foo, bar, baz) みたいに書けば、
t.foo='blue', t.bar=42 みたいに表現できるよね。
• 作った式をクエリに変換して実行できると嬉しい
37. SQLAlchemyではこうなる
• select([col1, col2, ...], ...)
• column('foo')=='blue' & column('bar')==42
• t = table('mytable', column('foo'), column('bar'), ...)
select([t]).where(t.c.foo=='blue', t.c.bar==42)
• query = select([t]).where(t.c.bar==42)
engine.execute(query).fetchall()
49. ここまでのまとめ
• table() や column() を使ってテーブルやカラムを表せる
• カラム定義つきで tbl=table(...) を作ると、tbl.c.colname でカラムオブ
ジェクトにアクセスできる
• colname と何かを比較すると条件式オブジェクトになる
• select() にカラム(やテーブル)の列を指定するとSELECT文を表すオブ
ジェクトになる
• select() や テーブルのメソッドを呼び出して generative に式を作れる
• engine.execute(sql式) でクエリを実行できる
51. こんなモデルで
film (作品)
-------------------------
film_id PK
title タイトル
description 説明
release_year 年
language_id 言語
original_language_id
rental_rate 貸出料金
length 視聴時間
replacement_cost 原価
rating 対象年齢
last_update 最終更新
category (ジャンル)
-------------------------
category_id PK
name ジャンル名
last_update 最終更新
film_category
-------------------------
film_id 作品ID
category_id カテゴリID
last_update 最終更新
52. 実現例
(他にも書き方があります。試してみて!)
>>> category = table('category',
... column('category_id'),
... column('name'))
>>> f, fc, cat = film, film_category, category
>>> j = f.join(fc,
... onclause=(f.c.film_id==fc.c.film_id))
... .join(cat,
... onclause=(cat.c.category_id==
... fc.c.category_id))
...
>>> query = select([f.c.title, f.c.rental_rate], from_obj=j)
... .where(category.c.name=='Animation'))
...
>>> e..execute(query).fetchall()
[('ALTER VICTORY', 0.99), ('ANACONDA CONFESSIONS', 0.99), ...]
58. スキーマ定義って何
• table() や column() との違い:
テーブルやスキーマの属性を設定できる
カラムのデフォルト値とか、インデクスとか、制約とか
定義に基づいてCREATE TABLEできる
• クエリを書くだけならいらないですよね?
基本のSQL式だけより、書きやすくなります
• じゃ、知らなくてもいい?
本気のソフトウェア開発で使う時は必要です。
ORM使いたい人は覚えましょう
61. from sqlalchemy import Column, MetaData, Table
from sqlalchemy import TIMESTAMP, INTEGER
location = Table(
'location',
MetaData(),
Column('location_id', INTEGER, primary_key=True),
Column('store_id', INTEGER, nullable=False),
Column('last_update', TIMESTAMP, nullable=False,
server_default='CURRENT_TIMESTAMP',
server_onupdate='CURRENT_TIMESTAMP'),
)
テーブルを定義する
location (商品棚)
---------------------------------
location_id INTEGER 棚番号
store_id INTEGER 店舗ID
last_update DATETIME 最終更新
66. >>> from sqlalchemy import Index
>>> f = Table('film', MetaData(), Column...)
>>> Index('k_title', f.c.title)
>>>
>>> from sqlalchemy import ForeignKeyContraint
>>> fc = Table('film_category', MetaData(),
... Column('film_id',
... ForeignKey(f.c.film_id)), ...)
>>> str(f.join(fc)) # onclause がなくても JOIN 可
'film_category JOIN film ON film.film_id = film_category.film_id'
>>> Index('k_title', f.c.title)
Index('k_title', Column('title', VARCHAR(length=255), table=<film>))
>>> f.indexes
{Index('k_title', Column('title', VARCHAR(length=255), table=<film>))}
インデクスと制約
68. ここまでのまとめ
• Table() や Column() でテーブルを定義すると、DDL を
実行できる
カラムの制約やインデクスも貼れる
• Table() や Column() は、 table(), column() と同じよう
に扱える
70. ORMって何だろう
• オブジェクトとリレーショナル(DB) のマップ (対応付け)
DBの内容をデータオブジェクトとして扱えるよう頑張る存在
• ActiveRecord パターンでの実現が華やか
• 1テーブルを1クラス、1レコードを1オブジェクトに対応付ける仕
組がよくある
• 外部キーを元に別テーブルのレコード(別クラスのインスタンス)
を参照できたりする
• カラムデータをプロパティやアトリビュートでアクセスできる
ことがある
89. ハンズオン: ORM
• category テーブルをORMで定義
してみましょう
• セッションを作って、Category
のモデルのクエリを実行しましょ
う
• Nature というカテゴリを追加し
ましょう。
• NatureをGeographyに変更しま
しょう
• Geographyを削除しましょう