根据GORM 的文档:
Updates支持使用struct或map[string]interface{}更新,使用struct更新时默认只更新非零字段
我的数据库中已有一个ServiceID 为 的条目abc123。我正在尝试获取一个如下所示的对象:
Service{
ID: "abc123",
Name: "new service name",
CreatedAt: nil,
}
Run Code Online (Sandbox Code Playgroud)
并用它来更新我现有的记录。但是当我打电话时:
tx.Model(&service).Updates(service)
Run Code Online (Sandbox Code Playgroud)
CreatedAt数据库中的值将被覆盖nil。如何更新数据库记录而不覆盖该CreatedAt值?
更新:下面是我的Service结构
type Service struct {
ID string `gorm:"not null;type:char(32);primary_key;column:id"`
Name string `json:"name" gorm:"size:50;not null;"`
CreatedAt *time.Time
UpdatedAt time.Time
DeletedAt *time.Time `gorm:"index"`
}
Run Code Online (Sandbox Code Playgroud)
我已经为我的Service结构尝试了两种不同的变体。另一个是与CreatedAt类型time.Time而不是*time.Time。它将用*time.Time空值覆盖我的数据库中的值。它尝试用time.Time未初始化的时间值覆盖数据库中的值并抛出错误:Error 1292: Incorrect datetime value: '0000-00-00' for column 'created_at' at row 1
time.Time结构内字段类型的零值或默认值是time.Time{}。使用 时Updates,要么不填充该CreatedAt字段,要么time.Time{}为其分配值。
在下面的示例中,CreatedAt在两种情况下都会打印出字段的默认值或零值。
package main
import (
"fmt"
"time"
)
type T struct {
CreatedAt time.Time
C int
S string
}
func main() {
fmt.Println(T{C: 1, S: "one"})
fmt.Println(T{C: 2, S: "two", CreatedAt: time.Time{}})
}
// {0001-01-01 00:00:00 +0000 UTC 1 one}
// {0001-01-01 00:00:00 +0000 UTC 2 two}
Run Code Online (Sandbox Code Playgroud)
编辑:
另外,我不确定CreatedAt: nil,如果该CreatedAt字段是time.Time类型而不是*time.Time.
由于您已将Service结构和CreatedAt字段类型更新为*time.Time,因此以下操作应该有效:
tx.Model(&service).Updates(Service{Name: service.Name}) // add all fields that you want to be updated.
// resulting query
// UPDATE services SET name = 'new service name' WHERE id = 'abc123';
Run Code Online (Sandbox Code Playgroud)
官方 GORM 示例在这里
此外,您可以省略该created_at字段,如下所示:
tx.Model(&service).Omit("created_at").Updates(service)
Run Code Online (Sandbox Code Playgroud)