Symfoware

Symfowareについての考察blog

SQLAlchemyの使い方3 データの取得方法いろいろ

SQLAlchemyの使い方を勉強してます。

前回に引き続き、チュートリアルに沿って進めてみます。
http://docs.sqlalchemy.org/en/latest/orm/tutorial.html


今回もPostgreSQLに作成したstudentsテーブルのデータを使用します。


sample=# select * from students;
id |        name        |         kana        
----+--------------------+--------------------------
18 | 西住 みほ    | ニシズミ ミホ
19 | 武部 沙織    | タケベ サオリ
20 | 五十鈴 華    | イスズ ハナ
21 | 秋山 優花里 | アキヤマ ユカリ
22 | 冷泉 麻子    | レイゼイ マコ
(5 rows)







Returning Lists and Scalars



データの取得方法の例です。

queryの実行結果自体をループで使用出来ます。


  1. import sqlalchemy
  2. import sqlalchemy.orm
  3. import sqlalchemy.ext.declarative
  4. Base = sqlalchemy.ext.declarative.declarative_base()
  5. class Student(Base):
  6.     __tablename__ = 'students'
  7.     id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
  8.     name = sqlalchemy.Column(sqlalchemy.String(20))
  9.     kana = sqlalchemy.Column(sqlalchemy.String(40))
  10. url = 'postgresql://pgadmin:password@192.168.1.101:5432/sample'
  11. engine = sqlalchemy.create_engine(url, echo=False)
  12. # セッションを作成
  13. Session = sqlalchemy.orm.sessionmaker(bind=engine)
  14. session = Session()
  15. # データを検索
  16. students = session.query(Student)
  17. print(type(students))
  18. for row in students:
  19.     print("%d, %s" % (row.id, row.name))




この時のオブジェクトは、「class 'sqlalchemy.orm.query.Query'」




all()を指定すると、リストで結果が取得できます。
ソースの抜粋はこんな感じ。


  1. students = session.query(Student).all()
  2. print(type(students))
  3. for row in students:
  4.     print("%d, %s" % (row.id, row.name))



この時は、「type 'list'」が得られます。




first()を指定すると、最初の1つが取得できます。


  1. student = session.query(Student).first()
  2. print(type(student))
  3. print("%d, %s" % (student.id, student.name))





実行結果


$ python sample.py
<class '__main__.Student'>
18, 西住 みほ






one()を指定すると、first()と同じ効果かな?と思いましたがエラーになります。


  1. student = session.query(Student).one()
  2. print(type(student))
  3. print("%d, %s" % (student.id, student.name))





「sqlalchemy.orm.exc.MultipleResultsFound」が発生します。。


$ python sample.py
Traceback (most recent call last):
File "sample.py", line 24, in <module>
    student = session.query(Student).one()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2364, in one
    "Multiple rows were found for one()")
sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one()





結果が1件のみとなるよう条件を指定してみます。


  1. student = session.query(Student).filter(Student.name=='西住 みほ').one()
  2. print(type(student))
  3. print("%d, %s" % (student.id, student.name))




データが取得出来ました。


$ python sample.py
<class '__main__.Student'>
18, 西住 みほ





検索結果が0件の場合。


  1. student = session.query(Student).filter(Student.name=='西住 まほ').one()
  2. print(type(student))
  3. print("%d, %s" % (student.id, student.name))




「sqlalchemy.orm.exc.NoResultFound」が発生します。


$ python sample.py
Traceback (most recent call last):
File "sample.py", line 24, in <module>
    student = session.query(Student).filter(Student.name=='西住 まほ').one()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2361, in one
    raise orm_exc.NoResultFound("No row was found for one()")
sqlalchemy.orm.exc.NoResultFound: No row was found for one()





結果が0件の条件で、first()を使用した場合。


  1. student = session.query(Student).filter(Student.name=='西住 まほ').first()
  2. print(type(student))
  3. print("%d, %s" % (student.id, student.name))




戻り値としてNoneが帰ってくるようです。


$ python sample.py
<type 'NoneType'>
Traceback (most recent call last):
File "sample.py", line 27, in <module>
    print("%d, %s" % (student.id, student.name))
AttributeError: 'NoneType' object has no attribute 'id'





ログインユーザーを確定するような、必ず検索結果が1件になるとき
one()を使うと良さそうです。






Using Literal SQL



filterやorder_byで直接SQL文の条件式が指定できます。

まずfilter


  1. students = session.query(Student).filter('id=20')
  2. for row in students:
  3.     print("%d, %s" % (row.id, row.name))




実行結果。


$ python sample.py
20, 五十鈴 華





order_by


  1. students = session.query(Student).order_by('id desc')
  2. for row in students:
  3.     print("%d, %s" % (row.id, row.name))




実行結果


$ python sample.py
22, 冷泉 麻子
21, 秋山 優花里
20, 五十鈴 華
19, 武部 沙織
18, 西住 みほ





パラメーター名を使用して値の設定も可能。


  1. students = session.query(Student).filter('id=:id').params(id=21)
  2. for row in students:
  3.     print("%d, %s" % (row.id, row.name))




実行結果


$ python sample.py
21, 秋山 優花里








Counting



検索結果のカウントは、単に「count()」としてやればOK。


  1. students_count = session.query(Student).count()
  2. print(students_count)




実行結果


$ python sample.py
5




sqlalchemy.funcを使用して、countに使用する列名を指定可能。
「*」を指定。


  1. students_count = session.query(sqlalchemy.func.count('*')).select_from(Student).scalar()
  2. print(students_count)




「id」を指定。


  1. students_count = session.query(sqlalchemy.func.count(Student.id)).select_from(Student).scalar()
  2. print(students_count)




※結果は同じです。




countとgroup byを組み合わせる例。


  1. students = session.query(sqlalchemy.func.count(Student.id),Student.name).\
  2.     group_by(Student.name).all()
  3. for row in students:
  4.     print('%d, %s' % (row[0], row[1]))




実行結果


$ python sample.py
1, 五十鈴 華
1, 西住 みほ
1, 秋山 優花里
1, 武部 沙織
1, 冷泉 麻子





countの結果に列名を付けたい場合は、
SQLAlchemyの使い方2 データの更新と検索、ロールバック
ここの「列の別名」でやった要領で、labelを定義します。


  1. students = session.query(sqlalchemy.func.count(Student.id).label('count'),Student.name).\
  2.     group_by(Student.name).all()
  3. for row in students:
  4.     print('%d, %s' % (row.count, row.name))



関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/03/30(日) 21:56:09|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<SQLAlchemyの使い方4 Unicode文字列の使用 | ホーム | SQLAlchemyの使い方2 データの更新と検索、ロールバック>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1375-48a0e578
この記事にトラックバックする(FC2ブログユーザー)