SQLAlchemyで遊んでみる。その2

SQLAlchemyで遊んでみる。その1 の続き。

今回は SELECT のやり方をちょくちょく試してみたよ。 まぁ、前回同様ドキュメントに従ったり従わなかったりはその場の気分でやっております。

テーブル定義とかは前回のものをそのまま使った。 ので、とりあえずはインポートする。 ただ、データは新しく作り直す事にした。

>>> import sha
>>> from tutorials import *

>>> # 一度テーブルを全部ドロップする。
>>> meta.drop_all(checkfirst=True)

>>> # テーブル作成。
>>> meta.create_all(checkfirst=True)

Session オブジェクトを作って、新しくデータを登録していく。

>>> # Sessionクラスを作る。
>>> Session = sessionmaker(autoflush=True, transactional=True)

>>> # Sessionクラスのインスタンス化。
>>> sess = Session()

>>> # とりあえず10個テストデータを作る。
>>> for i in range(10):
...    a = 'test%s' % (i + 1)
...    sess.save(User(a, sha.new(a).hexdigest()))

>>> # ココでコミット。
>>> sess.commit()

何も考えず全部取り出すならこんな感じになるらしい。

>>> sess.query(User).all()
2007-08-27 02:21:08,185 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:21:08,186 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User('test1', 'b444ac06613fc8d63795be9ad0beaf55011936ac')>,
 <User('test2', '109f4b3c50d7b0df729d299bc6f8e9ef9066971f')>,
 <User('test3', '3ebfa301dc59196f18593c45e519287a23297589')>,
 <User('test4', '1ff2b3704aede04eecb51e50ca698efd50a1379b')>,
 <User('test5', '911ddc3b8f9a13b5499b6bc4638a2b4f3f68bf23')>,
 <User('test6', 'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>,
 <User('test7', 'ea3243132d653b39025a944e70f3ecdf70ee3994')>,
 <User('test8', 'd03f9d34194393019e6d12d7c942827ebd694443')>,
 <User('test9', '53d525836cc96d089a5a4218b464fda532f7debe')>,
 <User('test10', '168f4029f416ee06565f12e697dfc1534ae69d32')>]

>>> # コレでもいける。
>>> for row in sess.query(User):
...    print row
2007-08-27 02:22:33,576 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:22:33,577 INFO sqlalchemy.engine.base.Engine.0x..d0 []
<User('test1', 'b444ac06613fc8d63795be9ad0beaf55011936ac')>
<User('test2', '109f4b3c50d7b0df729d299bc6f8e9ef9066971f')>
<User('test3', '3ebfa301dc59196f18593c45e519287a23297589')>
<User('test4', '1ff2b3704aede04eecb51e50ca698efd50a1379b')>
<User('test5', '911ddc3b8f9a13b5499b6bc4638a2b4f3f68bf23')>
<User('test6', 'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>
<User('test7', 'ea3243132d653b39025a944e70f3ecdf70ee3994')>
<User('test8', 'd03f9d34194393019e6d12d7c942827ebd694443')>
<User('test9', '53d525836cc96d089a5a4218b464fda532f7debe')>
<User('test10', '168f4029f416ee06565f12e697dfc1534ae69d32')>

特定のデータを取り出すのにインデクシングしてみる。

>>> # 最初だけ取り出す。
>>> sess.query(User)[0]
2007-08-27 02:23:20,282 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
 LIMIT 1 OFFSET 0
2007-08-27 02:23:20,283 INFO sqlalchemy.engine.base.Engine.0x..d0 []
<User('test1', 'b444ac06613fc8d63795be9ad0beaf55011936ac')>

>>> # 最後だけ取り出す。
>>> sess.query(User)[-1]
2007-08-27 02:25:15,941 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:25:15,942 INFO sqlalchemy.engine.base.Engine.0x..d0 []
<type 'exceptions.IndexError'>: list index out of range
>>> sess.query(User)[-2]
2007-08-27 02:26:05,141 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:26:05,142 INFO sqlalchemy.engine.base.Engine.0x..d0 []
<User('test10', '168f4029f416ee06565f12e697dfc1534ae69d32')>

最後のデータを取り出すのにちょっと癖があるみたい。 しかも、最後のデータを取り出す形だと LIMIT, OFFSET が付かないらしい。 まぁ、可変長のデータに対してデータ取得前に長さが分かるはずないから当然だとは思う。

次にスライシングもやってみる。

>>> # 適当な範囲指定。
>>> sess.query(User)[1:5].all()
2007-08-27 02:30:12,270 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
 LIMIT 4 OFFSET 1
2007-08-27 02:30:12,270 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User('test2', '109f4b3c50d7b0df729d299bc6f8e9ef9066971f')>,
 <User('test3', '3ebfa301dc59196f18593c45e519287a23297589')>,
 <User('test4', '1ff2b3704aede04eecb51e50ca698efd50a1379b')>,
 <User('test5', '911ddc3b8f9a13b5499b6bc4638a2b4f3f68bf23')>]

>>> # あえて範囲外を指定してみる。
>>> sess.query(User)[5:20].all()
2007-08-27 02:31:09,289 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
 LIMIT 15 OFFSET 5
2007-08-27 02:31:09,290 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User('test6', 'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>,
 <User('test7', 'ea3243132d653b39025a944e70f3ecdf70ee3994')>,
 <User('test8', 'd03f9d34194393019e6d12d7c942827ebd694443')>,
 <User('test9', '53d525836cc96d089a5a4218b464fda532f7debe')>,
 <User('test10', '168f4029f416ee06565f12e697dfc1534ae69d32')>]

>>> # リミットをマイナス値指定。
>>> sess.query(User)[5:-2]
2007-08-27 02:33:32,609 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:33:32,609 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User(u'test6', u'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>,
 <User(u'test7', u'ea3243132d653b39025a944e70f3ecdf70ee3994')>,
 <User(u'test8', u'd03f9d34194393019e6d12d7c942827ebd694443')>]
>>> sess.query(User)[5:-1]
2007-08-27 02:35:16,456 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
2007-08-27 02:35:16,456 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User(u'test6', u'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>,
 <User(u'test7', u'ea3243132d653b39025a944e70f3ecdf70ee3994')>,
 <User(u'test8', u'd03f9d34194393019e6d12d7c942827ebd694443')>,
 <User(u'test9', u'53d525836cc96d089a5a4218b464fda532f7debe')>]
>>> sess.query(User)[5:].all()
2007-08-27 02:37:55,613 INFO sqlalchemy.engine.base.Engine.0x..d0 SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.created_at AS users_created_at, users.updated_at AS users_updated_at
FROM users ORDER BY users.oid
 LIMIT -1 OFFSET 5
2007-08-27 02:37:55,616 INFO sqlalchemy.engine.base.Engine.0x..d0 []
[<User(u'test6', u'a66df261120b6c2311c6ef0b1bab4e583afcbcc0')>,
 <User(u'test7', u'ea3243132d653b39025a944e70f3ecdf70ee3994')>,
 <User(u'test8', u'd03f9d34194393019e6d12d7c942827ebd694443')>,
 <User(u'test9', u'53d525836cc96d089a5a4218b464fda532f7debe')>,
 <User(u'test10', u'168f4029f416ee06565f12e697dfc1534ae69d32')>]

インデクシングとスライシングとでリミットの挙動が違うのがちょっと気になる。 そんなものなのかなぁ?どうだろう?

細かいところが気になって全然進まないけど、継続して色々試していこう。 SQLを遅延評価してくれるところはかなり素敵。 all が付いたり付かなかったりしてるのもそのためっす。

Posted at: 
2007/08/27 02:53:46
0 Comments
0 TrackBacks
Tags: 
Python
SQLAlchemy
Trackback: 
http://humming.via-kitchen.com/2007/08/27/play-with-sqlalchemy-part2/trackback/

TrackBacks

まだ登録されていません。

Comments

まだ登録されていません。

Add Comment

Add Comment