Help us understand the problem. What is going on with this article?

GORM で Null アップデート

More than 1 year has passed since last update.

はじめに

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

takasp
Docker, Kubernetes, CircleCIなどを触るインフラエンジニアやってます。 最近はアプリケーションエンジニアとしてTypeScriptを書くことが増えてきました。
aircloset
「新しい当たり前を作る」を作ることをミッションに、airClosetを開発・運営しています。
http://corp.air-closet.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away