Bobのテーブル結合
code:go
📚 双方向のテーブル結合について
双方向結合の意味
Bob ORMは両方向からJOINできるように自動生成している:
// 1. master_booksを起点にauthorsをJOIN
dbmodels.SelectJoins.MasterBooks.InnerJoin.Author
// SQL: FROM master_books INNER JOIN authors ON authors.id = master_books.author_id
// 2. authorsを起点にmaster_booksをJOIN(逆方向)
dbmodels.SelectJoins.Authors.InnerJoin.MasterBooks
// SQL: FROM authors INNER JOIN master_books ON master_books.author_id = authors.id
なぜ双方向が必要?
ユースケースによって起点が変わるから:
1. 「この本の著者は誰?」 → master_booksが起点
SELECT * FROM master_books
JOIN authors ON authors.id = master_books.author_id
WHERE master_books.title LIKE '%Go%'
2. 「この著者の本は何?」 → authorsが起点
SELECT * FROM authors
JOIN master_books ON master_books.author_id = authors.id
WHERE authors.name = '山田太郎'
JOINの3種類の違い
InnerJoin: f(c, clause.InnerJoin), // 両方にデータがある場合のみ
LeftJoin: f(c, clause.LeftJoin), // 左側は全て、右側はあれば
RightJoin: f(c, clause.RightJoin), // 右側は全て、左側はあれば
具体例:
- InnerJoin: 著者が設定されている本だけ取得
- LeftJoin: 著者が未設定の本も含めて全て取得
- RightJoin: 本を書いていない著者も含めて取得(あまり使わない)
実装での使い分け
// 著者名で検索(著者が必須)→ InnerJoin
if query.AuthorName.Valid {
mods = append(mods, dbmodels.SelectJoins.MasterBooks.InnerJoin.Author)
}
// 全ての本を取得(著者情報はあれば)→ LeftJoin
if needAuthorInfo {
mods = append(mods, dbmodels.SelectJoins.MasterBooks.LeftJoin.Author)
}
JoinにはCRUDごとに種類がある
code:go
1. SelectJoins - データ取得時のJOIN
用途: SELECT文でデータを取得する時に使用
-- 例:本と著者情報を一緒に取得
SELECT * FROM master_books
INNER JOIN authors ON authors.id = master_books.author_id
使用例:
// 著者名で本を検索
mods = append(mods,
dbmodels.SelectJoins.MasterBooks.InnerJoin.Author)
2. UpdateJoins - 更新時のJOIN
用途: UPDATE文で関連テーブルの条件を使って更新
-- 例:特定の著者の本の価格を一括更新
UPDATE master_books
SET price = price * 1.1
FROM authors
WHERE authors.id = master_books.author_id
AND authors.name = '山田太郎'
使用例:
// 特定著者の本を一括更新
mods = append(mods,
dbmodels.UpdateJoins.MasterBooks.InnerJoin.Author)
mods = append(mods,
dbmodels.UpdateWhere.Authors.Name.EQ("山田太郎"))
3. DeleteJoins - 削除時のJOIN
用途: DELETE文で関連テーブルの条件を使って削除
-- 例:特定出版社の本を削除
DELETE FROM master_books
USING publishers
WHERE publishers.id = master_books.publisher_id
AND publishers.name = '廃業出版社'
使用例:
// 特定出版社の本を削除
mods = append(mods,
dbmodels.DeleteJoins.MasterBooks.InnerJoin.Publisher)
mods = append(mods,
dbmodels.DeleteWhere.Publishers.Name.EQ("廃業出版社"))
🎯 なぜ3種類必要?
SQLの文法が異なるから:
- SELECT: FROM table1 JOIN table2
- UPDATE: UPDATE table1 SET ... FROM table2
- DELETE: DELETE FROM table1 USING table2
Bob ORMは各SQL文に適した型安全なJOINを提供しています!
💡 実践的な使い分け
// 読み取り → SelectJoins
func (m *masterBook) Search(...) {
mods = append(mods,
dbmodels.SelectJoins.MasterBooks.InnerJoin.Author)
}
// 更新 → UpdateJoins(将来実装する場合)
func (m *masterBook) UpdateByAuthor(...) {
mods = append(mods,
dbmodels.UpdateJoins.MasterBooks.InnerJoin.Author)
}
// 削除 → DeleteJoins(将来実装する場合)
func (m *masterBook) DeleteByPublisher(...) {
mods = append(mods,
dbmodels.DeleteJoins.MasterBooks.InnerJoin.Publisher)
}