Python
ORM
Dataset

【dataset】pythonでDB処理を楽チンに!【ORM】【python】

はじめに

pythonからデータベースをいじる時に、クエリをベタ書きするんじゃなくてORMを利用することでコードがすっきりするのでサーバーサイドやデータサイエンスに興味ある人にはマストだと思います。

ORMとは?

オブジェクト関係マッピング(Object-Relational Mapping)の略称。

言語からSQLを操作する時に、SQLドライバを入れてクエリ書いて実行する(Ex. mysql-connecter)という方法がある。

でも、これだと上に書いたように処理が多い時に綺麗にコードが書きづらい!

ってことでそれを解消するのにORMが役にたつ!

簡単に言うとSQLを関数的に使うことができる。

今回使うpython用ORMは【dataset】

環境

OS:MacOS OSX10.11.6
言語:python3.5.2
ORM:dataset0.8.0
DBMS:mysql

導入

これだけ。

sudo pip install dataset

だけど、MySQLdbがimportできない!っていうエラー出ることがあります。

その時は、以下のパッケージをインストールしてください。

pip install mysqlclient

これで、python3でMySQLdbをimportすることができてdatasetをインストールすることができると思います。

実践

SQL文と対応させながら基本的な使い方を説明します。

今回は練習用に研究室のデータベースサーバー【db01】を使います。

データベースは【TrainLine】で、小田急線の駅名が入っています。

__________2017-04-15_22.43.26.png

接続

まず、DBと接続します。

import dataset

# 対象のDBを指定
DBMS = 'mysql'
USER = 'root'
PASS = '~'
HOST = '対象DBのIPアドレス'
DB     = 'TrainLine' 
TABLE='Station_Name'
# 文字コードで悩む人へ
CHARSET = 'utf8'

db = dataset.connect('{0}://{1}:{2}@{3}/{4}?charset={5}'.format(DBMS, USER, PASS, HOST, DB, CHARSET))
table = db[TABLE]

DBMS:MySQL,PostgreSQL,sqliteとか対象のDBMSを指定

USER:ログインしたいユーザー名を指定

PASS:パスワードが必要なユーザーの時は指定

HOST:サーバーのアドレスを指定(IPアドレスでも可)

DB:使用するDB名を指定

TABLE:使用するテーブル名を指定



これで実行してエラーが出なければ接続完了。

次に実際にSQLを実行していきます。

SELECT文(複数)

複数レコードをselectする時はfind()を使います。

# SQL:SELECT * FROM Station_Name
results = table.find()
for record in results:
    # OrderDict型で1レコードずつ出力される
    print(record)
    # カラムを指定することで特定の情報を引き出せる
    print(record['Station_ID'])
    print(record['Name'])

selectされたデータはOrderDict型で返ってきます。

ちなみにOrderDict型は、順番を保持した辞書型のデータです。

複数のレコードをselectしているため、for文を使うことで1レコードずついじれます。

1レコードに対して、カラムを指定することで情報を抽出できます。

terminal
===SQL:SELECT * FROM Staion_Name===
OrderedDict([('Station_ID', 2500101), ('Name', '新宿')])
2500101
新宿
OrderedDict([('Station_ID', 2500102), ('Name', '南新宿')])
2500102
南新宿
OrderedDict([('Station_ID', 2500103), ('Name', '参宮橋')])
2500103
参宮橋
OrderedDict([('Station_ID', 2500104), ('Name', '代々木八幡')])
2500104
代々木八幡
OrderedDict([('Station_ID', 2500105), ('Name', '代々木上原')])
2500105
代々木上原
・・・

WHERE句での指定SELECT

SQLで特定の情報を持つレコードをselectするのにWHERE句を使います。

このORMではfind関数の引数にカラムと値を指定することで実現できます。

## where句での指定
# SQL:SELECT * FROM Staion_Name WHERE Station_ID = 2500101
results = table.find(Station_ID=2500101)
for record in results:
    print(record)
terminal
===SQL:SELECT * FROM Staion_Name WHERE Station_ID = 2500101===
OrderedDict([('Station_ID', 2500101), ('Name', '新宿')])

LIMITの指定も可能

複数レコードをselectする際にレコード数を制限することができる。

## _limit変数でselectの数を制限
# SQL:SELECT * FROM Station_Name limit 10 
results = table.find(_limit = 10)
for record in results:
    print(record)
terminal
===SQL:SELECT * FROM Staion_ID = 2500101===
OrderedDict([('Station_ID', 2500101), ('Name', '新宿')])

SELECT文(単一)

単一のレコードだけをselectする時はfind_one()を使うとfor文を使わないでデータをいじれる。

# SQL:SELECT * FROM Staion_ID = 2500101
print(table.find_one(Station_ID = 2500101))
terminal
===SQL:SELECT * FROM Staion_Name limit 10===
OrderedDict([('Station_ID', 2500101), ('Name', '新宿')])
OrderedDict([('Station_ID', 2500102), ('Name', '南新宿')])
OrderedDict([('Station_ID', 2500103), ('Name', '参宮橋')])
OrderedDict([('Station_ID', 2500104), ('Name', '代々木八幡')])
OrderedDict([('Station_ID', 2500105), ('Name', '代々木上原')])
OrderedDict([('Station_ID', 2500106), ('Name', '東北沢')])
OrderedDict([('Station_ID', 2500107), ('Name', '下北沢')])
OrderedDict([('Station_ID', 2500108), ('Name', '世田谷代田')])
OrderedDict([('Station_ID', 2500109), ('Name', '梅ヶ丘')])
OrderedDict([('Station_ID', 2500110), ('Name', '豪徳寺')])

INSERT文(単一)

SQLだと覚えにくいINSERT文もORMを使うと直感的に操作できます。

INSERTしたいレコードデータは、dict型で生成します。

# INSERT文:insert()
# SQL:INSERT INTO Staion_Name VALUES (2500200, '新大久保')
## insertしたいレコード
data = dict(Station_ID=2500200, Name='新大久保')
table.insert(data)
for record in table.find(Station_ID=2500200): print(record)


terminal
===SQL:INSERT INTO Staion_Name VALUES (2500200, '新大久保')===
OrderedDict([('Station_ID', 2500200), ('Name', '新大久保')])
OrderedDict([('Station_ID', 2500200), ('Name', '新大久保')])

INSERT文(複数)

複数のレコードをいっきにINSERTする方法が以下です。

## 複数のinsert
print("===複数insert===")
table.insert_many([dict(Station_ID=2500201, Name='西日暮里'), dict(Station_ID=2500202, Name='五反田')])
time.sleep(3)
for ID in [2500201, 2500202]:print(table.find_one(Station_ID=ID))


terminal
===複数insert===
OrderedDict([('Station_ID', 2500201), ('Name', '西日暮里')])
OrderedDict([('Station_ID', 2500202), ('Name', '五反田')])

UPDATE文

INSERT文同様にレコードデータを生成します。

ポイントは生成したレコードとデータベースにあるUPDATEしたいレコードの値が共通のカラム(下ので例では、Station_ID)をupdate関数の第2引数に指定することです。

# UPDATE文:update()
# SQL:UPDATE Staion_Name SET (Name = 渋谷) WHERE Station_ID = 2500201
## updateしたいレコード
data = dict(Station_ID=2500201, Name='渋谷')
## updateするためのカラムを指定(第2引数)
table.update(data, ['Station_ID'])
print(table.find_one(Station_ID=2500201))


terminal
===SQL:UPDATE Staion_Name SET Name = 渋谷 WHERE Station_ID = 2500201===
OrderedDict([('Station_ID', 2500201), ('Name', '渋谷')])

DELETE文

削除したいレコードがあるときは、delete()を実行する。

delete関数の第1引数にレコードのプライマリキーのカラムと値を指定して削除ができます。

# DELETE文:delete()
# SQL:DELETE FROM Station_Name WHERE Station_ID = 2500202
for ID in [2500200, 2500201, 2500202]: table.delete(Station_ID=ID)
for ID in [2500201, 2500202]:print(table.find_one(Station_ID=ID))


terminal
===SQL:DELETE FROM Station_Name WHERE Station_ID = 2500202===
None
None

COUNT文

カラムの値を指定することでその値を持つレコード数を数えることができます。

このORMではWHERE句の不等式での指定ができないため、レコードが存在するかどうかに使えそう。

# COUNT文:count()
# SQL:SELECT COUNT(*) FROM Station_Name WHERE Station_ID = 2500101
## WHERE句は等式でしか指定できないためレコードを確かめるのとかに使える
print(table.count(Station_ID = 2500101))
print(table.count(Station_ID = 2500301))


terminal
===SQL:SELECT COUNT(*) FROM Station_Name WHERE Station_ID = 2500101===
1
0

終わりに

これでpython用ORM【dataset】の説明終わります。

最低限の使い方はわかると思います。

他にも機能を使いたければ、直接gitをリファレンスするといいと思います。



ORMは知っておいて損はない知識・技術だと思うので、自分が使い慣れてる言語で1つは身につけておくと良いと思います。

読んでくれた方の参考になれば幸いです。

参考URL