OR型をtable上でどう表現するか
以下の様な型を、どのようにtable上で表現するか
FP目線で言えば、代数的データ型のOR型やUnion型
OOP目線で言えば、継承のある型
そもそも、RDBと根本的に相性良くないよな、と思うmrsekut.icon
どれを採用しても、何かしらの短所がある
例えば以下の様なDomain Modelを考える
productは複数種類あるので、その構造によってtableを分けている
table:A
id name price height width
table:B
id name price length
table:C
id name price product_code
この時に、orderlineはどうやって定義するか?
Domain Modelはこういう構造
code:ts
type Order = {
id: OrderId;
orderLines: NonEmptyList<OrderLine>
..
}
type OrderLine = AOrderLine | BOrderLine | COrderLine
type AOrderLine = {
id: OrderLineId;
name: string;
price: number
height: number;
width: number;
}
type BOrderLine = {
id: OrderLineId;
name: string;
price: number;
length: number;
}
type COrderLine = {
id: OrderLineId;
name: string;
price: number;
productCode: number;
}
抽象と、具象ごとにtableを用意する
適切な制約をかけやすい
具象が増えるとcolumnが増える
table:orderline
name age a_id b_id c_id
hoge 20 1 NULL NULL
piyo 20 NULL 1 NULL
table:A
id status version
1 XXX 2
table:B
id priority
1 high
参照を逆転する
NULLが生じない
a,b,cとの間全てに中間テーブルを作る
table:OrderLine_A
orderline_id a_id
table:OrderLine_B
orderline_id b_id
table:OrderLine_C
orderline_id c_id
個々のテーブルも作る
table:orderline
id name price type
table:A
id height width
table:B
id length
table:C
id product_code
個々の中間テーブルを跨いで、orderline_idがユニークでないといけない
JOINが増える
具象ごとに、具体的なtableを用意する
どこが共通項目なのかわかりにくい
table:A
name age status version
hoge 20 XXX 2
table:B
name age priority
piyo 20 high
仮にorder(orderlineの上位)に紐付けるなら各tableにorder_idのようなcolumnを生やす
table:B
id order_id name age priority
1 1 piyo 20 high
この辺は良くないと思うので避けたい
汎用的なtableを用意する
制約を付けられないし、NULLも頻発する
table:orderline
name age status version priority
hoge 20 XXX 2 NULL
piyo 20 NULL NULL high
論外
kindでproductの種類を限定してkind_idでそのidを指定する
table:orderline
id order_id name kind kind_id
1 1 aaa A 100
2 1 bbb A 100
3 1 ccc C 101
table:A
id status version
1 XXX 2
table:B
id priority
1 high
kind_idに対して外部キー制約を付けることができない
OUTER JOINすることでNULLが入るが一応目的のtableは作れる
他
これは意味が変わるので適切かどうかは場合に依る