怠惰な人のための超お手軽 ORマッパー dataset

# はじめに
みなさん、ORM使ってますか？
Python における ORMだと以下のようなものがあります。

- [SQLAlchemy](http://www.sqlalchemy.org/)
- [Storm](https://storm.canonical.com/)
- [Peewee](http://docs.peewee-orm.com/en/latest/)
- [Django's ORM](https://docs.djangoproject.com/en/1.9/topics/db/models/)

これらにかぎらずORMは使おうとするとmodelを定義する必要があったりして、
既存のプロジェクトのDBに対してスクリプトを書いてサクッと使うとかにはなかなか大変ですよね。

そこで、面倒な model の定義なんて書かずにサクッと使える ORマッパー dataset のご紹介です。

[pudo/dataset](https://github.com/pudo/dataset)

model 定義が不要なので Java で[Hibernate ORM](http://hibernate.org/orm/)や PHP で [Doctrine](http://www.doctrine-project.org/) のプロジェクトでも
簡単に導入することができます。

なお、datasetの内部では SQLAlchemy を利用しています。

# SELECT

```python
import dataset

db = dataset.connect('mysql://root@127.0.0.1/information_schema')

table = db['COLLATIONS']
results = table.find(CHARACTER_SET_NAME='utf8', order_by='-ID', _limit=3)
for r in results:
    print(r)
    # OrderedDict([('COLLATION_NAME', 'utf8_general_mysql500_ci'), ('CHARACTER_SET_NAME', 'utf8'), ('ID', 223L), ('IS_DEFAULT', ''), ('IS_COMPILED', 'Yes'), ('SORTLEN', 1L)])
    # OrderedDict([('COLLATION_NAME', 'utf8_vietnamese_ci'), ('CHARACTER_SET_NAME', 'utf8'), ('ID', 215L), ('IS_DEFAULT', ''), ('IS_COMPILED', 'Yes'), ('SORTLEN', 8L)])
    # OrderedDict([('COLLATION_NAME', 'utf8_unicode_520_ci'), ('CHARACTER_SET_NAME', 'utf8'), ('ID', 214L), ('IS_DEFAULT', ''), ('IS_COMPILED', 'Yes'), ('SORTLEN', 8L)])
```

## SQL
上の例では次のようなSQLが実行されます

```sql

SELECT `COLLATIONS`.`COLLATION_NAME`, `COLLATIONS`.`CHARACTER_SET_NAME`, `COLLATIONS`.`ID`, `COLLATIONS`.`IS_DEFAULT`, `COLLATIONS`.`IS_COMPILED`, `COLLATIONS`.`SORTLEN` 
FROM `COLLATIONS` 
WHERE `COLLATIONS`.`CHARACTER_SET_NAME` = 'utf8' ORDER BY `COLLATIONS`.`ID` DESC 
 LIMIT 0, 3
```

## 制限
イコール条件でのWHERE句しかサポートされていないので、LIKE 条件や`count` 等 SQL関数 を使う場合は [SQLAlchemyの記法](http://docs.sqlalchemy.org/en/latest/core/tutorial.html#selecting) で `db.query()` を利用します。

# INSERT

まず空の DB を作成します。

```shell-session
$ mysqladmin create sandbox
```

辞書形式で INSERTするデータを渡します。

```python
import dataset

db = dataset.connect('mysql://root@127.0.0.1/sandbox')

table = db['Alchemist']

table.insert(dict(name='Alphonse Elric'))
table.insert_many([dict(name='Edward Elric', titled='Fullmetal'), dict(name='Roy Mustang', titled='Flame')])
```

これで3件のレコードが登録されます。

## SQL

では、発行されたSQLをみてみましょう。

```sql
SHOW FULL TABLES FROM `sandbox`
rollback
-- テーブル有無確認
DESCRIBE `Alchemist`
rollback
rollback
-- テーブル作成
CREATE TABLE `Alchemist` (
        id INTEGER NOT NULL AUTO_INCREMENT, 
        PRIMARY KEY (id)
)
commit
rollback
-- カラム追加
ALTER TABLE `Alchemist` ADD COLUMN name TEXT
commit
rollback
SHOW FULL TABLES FROM `sandbox`
-- テーブル確認
SHOW CREATE TABLE `Alchemist`
rollback
-- table.insert(dict(name='Alphonse Elric'))
INSERT INTO `Alchemist` (name) VALUES ('Alphonse Elric')
commit
rollback
-- カラム追加
ALTER TABLE `Alchemist` ADD COLUMN titled TEXT
commit
rollback
SHOW FULL TABLES FROM `sandbox`
SHOW CREATE TABLE `Alchemist`
rollback
-- table.insert_many([dict(name='Edward Elric', titled='Fullmetal'), dict(name='Roy Mustang', titled='Flame')])
INSERT INTO `Alchemist` (name, titled) VALUES 
('Edward Elric', 'Fullmetal'),
('Roy Mustang', 'Flame')
commit
```

`INSERT` するテーブルやカラムがなければ作るという挙動をします。なんと ~~恐ろしい~~ お手軽なのでしょう!
正直、プロダクション環境で使うにはオススメできません。

# その他
公式サイトのキャラクターロゴがかわいいです。
[dataset: databases for lazy people — dataset 0.6.0 documentation](https://dataset.readthedocs.org/en/latest/)

json 形式でSQLの結果を書き出すこともできます。
[DB のデータを json 形式でエクスポートする - Qiita](http://qiita.com/shoma/items/0b6ae0f5f2a0d46ae010)