ERMasterを使ってSQLアンチパターンを阻止しよう

※わりと初心者向けの記事になることをご了承ください。上級者からは総突っ込みを受けそうなのでハードルを下げておきます。

# ER図とは

ER図（ER diagram）はDBのつながりを図（ダイアグラム）で表現したもので、
各テーブルの外部キー、インデックスなどの関連性を示すのにもっともポピュラーな方法（だと私は考えている）。

～ここからすこし雑談～

例は以下に示していくつもりだが、複雑なDB構造を目の当たりにし、設計書もない場合、
**「デバッグしながら」**
**「画面操作しながら」**
**「保存ボタンを押したらどのテーブルに何が入るのか見ていく」**
みたいな不毛なことをやってテーブル構造を把握せざるを得ない。

本来ならテーブルの更新（create、alterなど）と同時にER図もメンテするフローになっていたら
**「XXサブのYYってどのテーブルに入るのでしょうか？」**
**「AAAテーブルのbbbカラムってどのテーブルとつながっているのですか？」**
のような無駄なコミュニケーションがなくなると考えている。

ただうちの会社では、機能開発においてER図が必須ではないので、
新人をチームに迎えるたびにこのようなコミュニケーションは頻発する。

たしかにメンテはめんどくさいが、いろいろ出来るみたいなので、
開発フローが未熟だったり固まっていないスタートアップ企業や個人で開発をするときは取り入れてみるのもいいかもしれない。

ちなみに私は個人で開発しているWebアプリでもER図を書くことがある（複雑になる場合）。


#ERMaster

何のツールがBestか分からないが、
うちの会社ではeclipseが最もポピュラーなIDEなので、
eclipseプラグインがあって最強らしいERMasterを使っていこうと思う。

##ERMasterのプラグインをインストールする

- eclipseは3.3以上を使ってください（最新は[こちら](https://www.eclipse.org/downloads/)）
- eclipseを開いて、Help > Install New Software... と選択
- Available Software というダイアログが開くのでAddボタンを押下
- Nameに「ERMaster」、Locationには「**http://ermaster.sourceforge.net/update-site/**」をコピペ
- Addボタンで追加できる
- Work Withの選択肢の中に登録したERMasterが出てくるので選択
- 下の枠にERMasterが出てくるのでチェックボックスにチェックをしてNext
- とにかくNext（チェックつけなおすとかは不要）
- 同意チェックしてFinish
- 警告が出るがinstall Anywayでインストール続行
- 画面の通りに設定していけばインストールができ、eclipse再起動を促してくるので従う
- 再起動すれば、「File > New > other」のなかにERMasterが出てくるのでこれで準備は完了。



#テーブル構造をER図にしていく

絶望しかけたテーブル構造を整理していく。
※ただし社外秘情報を含んでしまうためテーブルはサンプルのものを利用する。競馬好きなので競馬を例にする。

DBは以下の3つ

####競走馬情報
```
CREATE TABLE  IF NOT EXISTS horse_info (
	horse_id  varchar(80) not null,
	horse_name varchar(80)
);
```

####馬ごとのレースの結果
```
CREATE TABLE  IF NOT EXISTS race_result (
	horse_id  varchar(80) not null ,
	race_id  varchar(80) not null ,
	result varchar(80)	
);
```

####レース情報
```
CREATE TABLE  IF NOT EXISTS race_info_data (
	race_id  varchar(80) not null ,
	race_date varchar(80),
	race_name varchar(80)	
);
```

- File > New > other とたどりERMasterを選択
![新規作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/e18a50b3-96bd-fee9-8e9f-7cde04f8f0b0.png)

- 作成したいプロジェクトを選択しておく（まっさらのところには作れないっぽい）
- Nextでファイル名を決める（race_rsult_structureとする）
- databaseを選択（私はプライベートではPostgreSQLユーザーなのでPostgreSQLをえらぶ）
- FinishするとViewが出てくる
![ER図作成VIEW.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/7ee27936-74e9-be74-73a4-089c5a0e8e3a.png)


あとはここに上記の3個のテーブルを記述してつないでいく。

まず3つのテーブルを書き出します。
![テーブルを書き出すとこうなる.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/fd6a16c4-8a7e-c343-cd75-0f20403a0d63.png)


ここからつないでいくのですが、新規にテーブルを作るときはこれをやってはだめです。
今回の目的はアンチパターン防止です。
今回の3テーブルは馬の情報、レースの情報を**マスタ情報**として保持し、
それぞれのテーブルを結果のテーブルでつなぐことで以下のような最悪の構造を防ぐということをやりたいのです。

####競走馬のレース結果情報
```
CREATE TABLE  IF NOT EXISTS horse_race_result (
	horse_name varchar(80),
	race_date varchar(80),
	race_course varchar(80),
	race_name varchar(80),
	result varchar(80)
);
```
こうなると最悪なのは、レースの名前や馬の名前、情報をメンテしようとしたら
複数の行をメンテしなければならず、保守性が低くなります。
ディープインパクトは１頭しかいないし、2020年の有馬記念は1回しかありません。
なので、それぞれマスタで保持して唯一無二の状態にし、それぞれにIDを振って
外部キーで結合したresultだけを持つテーブルを作成すればよいということになります。

なので、まず2つのテーブル + resultだけを持ったテーブルにします。
![まず外部結合のキーはいらない.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/ac84e9c5-05fb-9cc5-79f1-50d93062d81c.png)

ここに**1：N関連**を使って**HORSE_INFO→RACE_RESULT、RACE_INFO→RACE_RESULT**という方向につないでいくと、
以下のようになります。
※**1：N関連**を**HORSE_INFO→RACE_RESULT、RACE_INFO→RACE_RESULT**という方向に使うのは、
上述した通り、ディープインパクトは１頭しかいないし、2020年の有馬記念は1回しかないので、**1**。
でもディープインパクトは有馬記念だけでなく天皇賞にも出てるし、凱旋門賞にも出ている。
つまり結果は複数存在するので**N**。
この考え方はDB構造、テーブル構造を検討するときに重要なので持っておくべきです。

![外部結合.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/46dca771-6464-1ada-5c06-4ee3db8bd874.png)

このように最初から何をキーにしなければならないのかを検討する以前に

- マスタ情報は何か
- 唯一無二のもの、複数あり得るものは何か

を検討し、ER図を作っていくと、間違っても前出のアンチパターンのようなDBを作ることはなくなるわけです。


# 最後に

実際の製品のテーブルのER図で絶望しています。皆さんきれいで保守しやすいDBを作りましょう。
そして機能追加、新プロダクト、新サブシステムを実装する場合はぜひER図を用いて考えてみてください。