LoginSignup
21
10

More than 5 years have passed since last update.

GORM で Null アップデート

Last updated at Posted at 2019-02-26

はじめに

Go の O/R マッパーである GORM を使っていて、NULL でのアップデートに困っていたので記載しておきます。

環境

  • Go 1.11.5
  • jinzhu/gorm v1.9.2

結論

以下の User モデルを更新する例です。

type User struct {
    ID   uint `gorm:"primary_key"`
    Age  int
    Name string
}

var user User
db.First(&user)

// 1 カラムの NULL アップデート
db.Model(&user).Update("name", gorm.Expr("NULL"))
// 実行 SQL : UPDATE `users` SET `name` = NULL  WHERE `users`.`id` = '1'

// 複数カラムの NULL アップデート
db.Model(&user).Updates(map[string]interface{}{
    "age":           18,
    "name":          gorm.Expr("NULL"),
})
// 実行 SQL : UPDATE `users` SET `age` = '18', `name` = NULL  WHERE `users`.`id` = '1'

SQL Expression によるアップデートに使用する gorm.Expr を使用して、直接 NULL を渡すことで NULL でアップデートができることが分かりました。

試行錯誤

通常のアップデートであれば以下のように指定することで可能ですが、NULL でアップデートするには nil を渡すなどで上手くいきませんでした。

db.Model(&user).Updates(User{Age: 18, Name: "hello"})

nil でのアップデート

NULL を含んだ Insert 文を実行するには、対象のカラムをポインタにして nil を渡すことで作成されます。

type User struct {
    ID   uint `gorm:"primary_key"`
    Age  int
-   Name string
+   Name *string
}

実際に実行してみると、NULL で作成されていることが分かります。

user := User{ID: 1, Age: 18, Name: nil}
db.Create(&user)
// 実行 SQL : INSERT INTO `users` (`id`,`age`,`name`) VALUES ('1','18',NULL)

では、同じ要領でアップデートでもポインタにしたカラムに nil を渡してみると、無視されてしまうことが分かりました。

var user User
db.First(&user)

db.Model(&user).Updates(User{Age: 18, Name: nil})
// 実行 SQL : UPDATE `users` SET `age` = '18'  WHERE `users`.`id` = '1'

GORM のドキュメントを見ると以下のように書いてあったので、構造体で実行すると無視されてしまうようです。

When query with struct, GORM will only query with those fields has non-zero value, that means if your field's value is 0, '', false or other zero values, it won't be used to build query conditions,

参考

How Do I Set a Field To NULL?
GORM

21
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
10