今さらPython3 (56) - RDBMS
第8章のリレーショナルデータベースのところです。
- 作者: Bill Lubanovic,斎藤康毅,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/12/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
PythonとRDBMSをつなぐ
と言えば、かつてFilemakerとPython(2.7)を繋げてゴニョゴニョしたことがありました。その時の様子はこの記事から5回シリーズぐらいでやったはず。
RDBMSとかSQLとは?的な問いについては、他に当たってもらうとして、この中ではPythonの中で使うというところを見る。
このモジュールを直接使うというより、使用しているDBに依存したものが出ているはず。
SQLite
やっぱり最初はこれでしたか。昔iPhoneアプリを作ったときにも、最初はこれを使っていたね。
>>> import sqlite3 >>> conn = sqlite3.connect('enterprise.db') >>> curs = conn.cursor() >>> curs.execute('''CREATE TABLE zoo (critter VARCHAR(20) PRIMARY KEY, count INT, damages FLOAT)''') <sqlite3.Cursor object at 0x101b82730> >>>
えっと、意味を確認。enterprise.dbというファイルに接続して、zooというテーブルを作りますと。テーブル内の項目は、critterという可変長文字列がプライマリキー項目、countという数字の項目、damagesという浮動小数点項目ですと。本の中には整数型と改訂あるけど、execute文を見る限りはFLOATで作っているので誤植だね。
ファイルがない場合は作ってくれるというお手軽さ。
>>> curs.execute('INSERT INTO zoo VALUES("duck", 5, 0.0)') <sqlite3.Cursor object at 0x101b82730> >>> curs.execute('INSERT INTO zoo VALUES("bear", 2, 1000.0)') <sqlite3.Cursor object at 0x101b82730> >>> ins = 'INSERT INTO zoo (critter, count, damages) VALUES(?, ?, ?)' >>> curs.execute(ins, ('weasel', 1, 2000.0)) <sqlite3.Cursor object at 0x101b82730>
書きっぷりは少し違うものの、エントリを3つINSERTしていますと。てか、SQLiteだとcommitいらないんだっけ?
>>> curs.execute('SELECT * FROM zoo') <sqlite3.Cursor object at 0x101b82730> >>> rows = curs.fetchall() >>> print(rows) [('duck', 5, 0.0), ('bear', 2, 1000.0), ('weasel', 1, 2000.0)] >>>
そんな疑問も、SELECTで中身を出してみれば解決。はい、ちゃんと3件登録されていましたね。ちなみに、タプルのリストとして出力されることも確認できたね。
>>> curs.execute('SELECT * FROM zoo ORDER BY count') <sqlite3.Cursor object at 0x101b82730> >>> rows = curs.fetchall() >>> print(rows) [('weasel', 1, 2000.0), ('bear', 2, 1000.0), ('duck', 5, 0.0)] >>>
countを昇順でソートしているパターン。最初、damageに目が行って、なんで降順なの?と思ってしまった。
>>> curs.execute('SELECT * FROM zoo ORDER BY count DESC') <sqlite3.Cursor object at 0x101b82730> >>> rows = curs.fetchall() >>> print(rows) [('duck', 5, 0.0), ('bear', 2, 1000.0), ('weasel', 1, 2000.0)] >>>
降順オプションはDESCをつけるのね。DESCENDINGかと思ってました。ちなみに、この本にも書いてあったけど、テーブルと項目名は小文字、それ以外のキーワードは大文字で書くようにしてます。(本は一部、fromって小文字で書いてあるところがあったけどね)
次は、damageが最大のモノを選択。これで良いのかなと思ったら、ちと失敗。
>>> curs.execute('SELECT MAX(damages) FROM zoo') <sqlite3.Cursor object at 0x101b82730> >>> rows = curs.fetchall() >>> print(rows) [(2000.0,)]
damageの金額だけ出てきちゃったので、ちゃんと本と同じようにやりましょう。
>>> curs.execute('''SELECT * FROM zoo WHERE damages = (SELECT MAX(damages) FROM zoo)''') <sqlite3.Cursor object at 0x101b82730> >>> rows = curs.fetchall() >>> print(rows) [('weasel', 1, 2000.0)] >>>
なるほどね。
>>> curs.close() >>> conn.close()
後始末はお忘れなく。てか、withは使えないのかな?てか使えたような気がする。
>>> with conn.cursor() as curs: ... curs.execute('SELECT * FROM zoo') ... rows = curs.fetchall() ... Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: __exit__ >>>
・・・ダメだったか。
MySQL, PostgreSQL
同じレッスンを繰り返してくれるのかなと思ったら、そうも行かないようで、ドライバの紹介で終わってますね。まずは、MySQLから。
github.com
MySQLConnector http://dev.mysql.com/doc/connector-python/en/
oursqlWelcome to oursql’s documentation! — oursql v0.9.2 documentation
3つ載っているけど、少し前に調べたときはMySQLConnectorがしばらく放置されている感じだったので、PyMySQLを入れたという経緯あり。
>>> import pymysql
>>>
うん。入ってる。あと書き忘れたけど、MariaDBでも問題なく使えます。
PostgreSQLの場合は、以下の2つが紹介されている。
日本語でググった限りだと、上の方が優勢っぽく見える。将来的にPostgreSQLを使うケースが出たら読み込んでみようかな。
(つづく)