RDBでテーブルの作り方が良くわからなくなってきたので、いったんまとめてみた
カーディナリティや依存関係*1、関係テーブル、正規化など、曖昧な知識のままなので、ちょっとまとめてみます。
経験からなんとなくは分かっているつもりですが、このままだと誰かに説明することもできないし、間違いに気がつかないかもしれない。
一度アウトプットすると整理されるらしいし、間違ってるかもしれないけど書いちゃいます。
なので、つっこみ歓迎です。
題材があったほうが書きやすいので、サンプルのER図を作りました。
- ユーザーとそのプロフィール。
- ユーザーが投稿した記事。
- 記事にフォークソノミーなタグ付け。
こんなデータが格納できる、簡易ブログというか簡易SNSの一部分といったイメージです。
カーディナリティ
エンティティ*2間の関係。
- 一対一 (one-to-one)
- [user] と [profile] の関係。ユーザー1人にプロフィールも1個。*3
- 一対多 (one-to-many)
- [user] と [post] の関係。ユーザー1人が、記事を0個以上からn個まで投稿していきます。
- 多対多 (many-to-many)
- [tagged] という関係テーブルを介した [post] と [tag] の関係。記事に対して0個からn個までのタグが付くし、とあるタグが0個からn個の記事に付けられます。
関係テーブル
リレーショナルデータベースでは、多対多の関係をそのまま作れないので、一対多に分解します。
その際、2個に分けたテーブルの対照表が必要になり、それが関係テーブルです。
関係テーブルは実体がなく、ER図では多対多を表すこともできます。
なので、ER図では関係テーブルは書かず、RDB上に実装する際に作るという意見も見かけたけど、ER図に書いちゃったほうが分かりやすいという意見も。
書いちゃったほうが分かりやすいですね。
非正規形を第1正規形にして、さらに第2正規形にすると、関係テーブルが出来上がってたりするみたい。
断言した解説があったわけじゃないけど、色々調べてたらなんとなくそうなってるかなと。
ER図について
ER図の記述法にはいくつかあるようで、よく見かけるのはIE*4表記とIDEF1Xです。
サンプルはIE表記で作ってます。
余談だけど、どちらの記述法もカーディナリティを形で表します。
クラス図の多重度みたいな表現にしてくれれば分かりやすいのに。
依存関係
いろいろ英語のサイトも調べた結論(今のところ)
独立なら:
子エンティティは角の尖った四角形で書き、関係は点線で書く。
子エンティティは主キーに親エンティティーを外部キーとして持たない。依存なら:
子エンティティは角の丸い四角形で書き、関係は実線で書く。
子エンティティは主キーに親エンティティーを外部キーとして持つ。みたい。なんで角の尖った四角形の場合は必ず関係は点線で書く。世の中にそうなってない解説ページが山程あるんで自信ないけど。
追記:
あーたぶんわかった。依存エンティティでもエンティティへの外部キーを主キー以外にもってるのもあるから、そういうのは点線で書くのか。
http://d.hatena.ne.jp/name-3333/20090219/1234992493
まとまった記事があったので引用です。
四角形で書き〜〜のあたりはIDEF1Xで書いたER図の話なので置いといて、主キーと外部キーのところがポイント。
サンプルでいうと [profile] が [user] に依存してます。
[user] が親で [profile] が子です。
エンティティの依存関係について - kanonjiの日記
エンティティの依存関係について、追加で調べてみました。
でも、少し分かった気がしたんですが、新たな疑問も出てきちゃってます。
関係テーブルはどうする?
[post] と [tag] の関係テーブルである [tagged] ですが、これを独立にするか依存にするが良く分からない。
id_post と id_tag のどちらも、[tagged] 内ではユニークにはならないので、id というプライマリーキーを作ってます。
そうすると、[tagged] は独立という事になります。
でも id_post と id_tag での複合プライマリーキーを作れば、id が要らなくなるので依存にもできるかなと。
ちゃんと基底から理解してないから、分からなくなるんだろうけど。
主キーには人工キーを使うか自然キーを使うか - kanonjiの日記
id という主キーを作るか、複合キーで主キーを作るかは、この人工キー or 自然キーのどちらの方針にするかに寄るみたいです。