👋
gormでに更新処理における書き方による挙動の違い
はじめに
gormでは更新の書き方が複数あって、挙動がそれぞれ異なるのでまとめる
書き方と発行されるSQL
以下のようなテーブルの更新を考える
type Table struct {
ID int
C1 string
C2 string
C3 *string
UpdatedAt time.Time
CreatedAt time.Time
}
1. Save
Save
メソッドを用いる場合
db.Save(&Table{
ID: 1,
C1: "hoge",
C3: nil,
})
以下のようなSQLが発行される
UPDATE
`tables`
SET
`c1` = 'hoge',
`c2` = '',
`c3` = NULL,
`updated_at` = '2022-10-30 23:11:15.142',
`created_at` = '0000-00-00 00:00:00'
WHERE
`id` = 1
- ゼロ値への更新が可能
-
updated_at
は更新してくれる
2. Updates
Updates
メソッドを用いる場合
db.Updates(&Table{
ID: 1,
C1: "hoge",
C3: nil,
})
以下のようなSQLが発行される
UPDATE
`tables`
SET
`c1` = 'hoge',
`updated_at` = '2022-10-30 23:11:15.144'
WHERE
`id` = 1
- ゼロ値への更新はできない
-
updated_at
は更新してくれる
3. Updates (with map)
Updates
メソッドに、mapを渡す場合
db.Model(Table{}).
Where("id = ?", 1).
Updates(map[string]any{
"C1": "hoge",
"C3": nil,
})
以下のようなSQLが発行される
UPDATE
`tables`
SET
`c1` = 'hoge',
`c3` = NULL,
`updated_at` = '2022-10-30 23:11:15.147'
WHERE
id = 1
- ゼロ値への更新は可能
-
updated_at
は更新してくれる
4. Create (DUPLICATE KEY UPDTE)
Create
を用いて以下のように更新する場合
db.
Clauses(
clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
},
).
Create(&Table{
ID: 1,
C1: "hoge",
C3: nil,
})
以下のようなSQLが発行される
INSERT INTO `tables`(
`c1`,
`c2`,
`c3`,
`updated_at`,
`created_at`,
`id`
)
VALUES(
'hoge',
'',
NULL,
'2022-10-30 23:11:15.149',
'2022-10-30 23:11:15.149',
1
)
ON DUPLICATE KEY UPDATE
`id` = `id`
-
Save
と同じだがcreated_at
も更新される挙動になる
今回の自分の場合
要件として、今回は以下の条件を満たしたかった
- ゼロ値への更新は必要 → 1, 3, 4
-
created_at
は都度指定したくない(更新されなくていい) → 3 -
updated_at
は更新されてほしい → 1, 2, 3, 4
上記の条件であれば、3の書き方が都合が良かった
Discussion