PyPika の Query、Table の基本的な使い方

# PyPika とは
[kayak/pypika](https://github.com/kayak/pypika) は、 Python の SQL　クエリビルダーです。本記事ではこのライブラリの中心となる Query、 Table の使い方について紹介します。

# 環境
公式に記載のサポートされている Python のバージョンは `3.6` 以上。今回使用している Python のバージョンは `3.9.10` です。 PyPika のバージョンは、`0.48.8` を使用しています。

#1. Query
名前の通り `Query` クラスを使用して SQLクエリを組み立てることができます。
以下は、 `SELECT` 文の例です。[from_](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L361) メソッドを使用して組み立てることができます。実態は [QueryBuilder](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L671)　クラスの [from_](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L760) メソッドを呼んでおり、続けて [select](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L839) メソッドを使用する事により SELECT 文を組み立てています。クエリ文字列として出力する際は [get_sql メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L1218) を使用します。

```python
from pypika import Query

q = Query.from_('users').select('id', 'name', 'email')
print(q.get_sql())

# 出力
# SELECT "id","name","email" FROM "users"
```
ちなみに `__str__` メソッド にも [get_sql メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L1218)  を呼ぶように設定されているので `q` のまま print しても同じ結果となります。

それぞれ RDBMS によって、Query のサブクラスが提供されています。今回は、 MySQL を例に説明していきます。 MySQL の場合はダブルクォーテーションでエラーになってしまうので、`Query` クラスのサブクラスである [MySQLQuery](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/dialects.py#L63) を使用する必要があります。　Oracle や Postgre も同じように [dialects ファイル](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/dialects.py)でサブクラスが定義されていますので必要に応じて読み替えてください。

```python
from pypika import MySQLQuery as Query

q = Query.from_('users').select('id', 'name', 'email')
print(q.get_sql())

# 出力
# SELECT `id`,`name`,`email` FROM `users`
```

## INSERT
`INSERT` 文を組み立てる場合は、 [into　メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L436)を使用します。実態は、 [QueryBuilder](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L671) クラスの [into メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L829)を呼んでいるので、続けて [insert メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L878) を使用することにより `INSERT` 文を組み立てることができます。

```python
from pypika import MySQLQuery as Query

q = Query.into('users').insert(1, 'Taro', 'taro@example.com')
print(q.get_sql())

# 出力
# INSERT INTO `users` VALUES (1,'Taro','taro@example.com')
```

## UPDATE
`UPDATE` 文を組み立てる際は、[update　メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L471)を使用します。実態は、 [QueryBuilder](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L671) クラスの [update メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L858) を呼んでいるので、続けて [set メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L1071) を使用することにより `UPDATE` 文を組み立てることができます。

```python
from pypika import MySQLQuery as Query

q = Query.update('users').set('name', 'Jiro')
print(q.get_sql())

# 出力
# UPDATE `users` SET `name`='Jiro'
```

## DELETE
`from_` メソッドを呼ぶのは `SELECT` 文のときと同じです。`DELETE` 文を組み立てる際は [delete メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L851)を使用します。

```python
from pypika import MySQLQuery as Query

q = Query.from_('users').delete()
print(q.get_sql())

# 出力
# DELETE FROM `users`
```


#2. Table
以下のように、　[Table クラス](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L116)を使用してもクエリを組み立てることができます。

```python
from pypika import Table

users = Table('users')
q = users.select(users.id, users.name, users.email)
print(q.get_sql())

# 出力
# SELECT "id","name","email" FROM "users"
```

[コードを読む](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L221)と内部では Query クラスを使用しているので、本記事冒頭で触れた `SELECT` 文の組み立てと同じことを行っています。`Query` クラスのサブクラスである [MySQLQuery](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/dialects.py#L63) を使用する際は以下のように　`_query_cls` に設定する必要があります。

```python
from pypika import MySQLQuery, Table

users = Table('users', query_cls=MySQLQuery)
q = users.select(users.id, users.name, users.email)
print(q.get_sql())

# 出力
# SELECT `id`,`name`,`email` FROM `users`
```

## INSERT
[Table クラス](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L116)で `INSERT` 文を組み立てる場合は、 [insert メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L231)を使用します。

```python
from pypika import MySQLQuery, Table

users = Table('users', query_cls=MySQLQuery)
q = users.insert(1, 'Taro', 'taro@example.com')
print(q.get_sql())

# 出力
# INSERT INTO `users` VALUES (1,'Taro','taro@example.com')
```

## UPDATE
[Table クラス](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L116)で `UPDATE` 文を組み立てる場合は、 [update メソッド](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L223)を使用します。

```python
from pypika import MySQLQuery, Table

users = Table('users', query_cls=MySQLQuery)
q = users.update().set(users.name, 'Jiro')
print(q.get_sql())

# 出力
# UPDATE `users` SET `name`='Jiro'
```

## DELETE
[Table クラス](https://github.com/kayak/pypika/blob/a7b01dac790f4c6e93a961b0be26a9645fe7cf5c/pypika/queries.py#L116) を見てわかる通り、 `DELETE` はサポートしていません。　前述の Query クラスで組み立てる他なさそうです。

#3. まとめ
本記事では、 PyPika の Query と Table の基本的な使い方について紹介しました。日本語のドキュメントが少ないかつ結合など他にも色々な組み立てができるので今後も記事を書いていけたらと思います。

# 参考リンク
[kayak/pypika](https://github.com/kayak/pypika)