创建记录

Generics API

user := User{Name: "Jinzhu"




    
, Age: 18, Birthday: time.Now()}

// Create a single record
ctx := context.Background()
err := gorm.G[User](db).Create(ctx, &user) // pass pointer of data to Create

// Create with result
result := gorm.WithResult()
err := gorm.G[User](db, result).Create(ctx, &user)
user.ID // returns inserted data's primary key
result.Error // returns error
result.RowsAffected // returns inserted records count

Traditional API

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

user.ID // 返回插入数据的主键
result.Error // 返回 error
result.RowsAffected // 返回插入记录的条数

用指定的字段创建记录

批量插入

Upsert Create With Associations 同样支持批量插入

注意 使用 CreateBatchSize 选项初始化GORM实例,此后进行创建和关联操作时所有的 INSERT 行为都会遵循初始化时的配置。

db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
CreateBatchSize: 1000,
})

db := db.Session(&gorm.Session{CreateBatchSize: 1000})

users = [5000]User{{Name: "jinzhu", Pets: []Pet{pet1, pet2, pet3}}...}

db.Create(&users)
// INSERT INTO users xxx (5 batches)
// INSERT INTO pets xxx (15 batches)

创建钩子

Hooks

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
u.UUID = uuid.New()

if u.Role == "admin" {
return errors.New("invalid role")
}
return
}

如果你想跳过 Hooks 方法,可以使用 SkipHooks 会话模式,例子如下

DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)

DB.Session(&gorm.Session{SkipHooks: true}).Create(&users)

DB.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(users, 100)

根据 Map 创建

使用 SQL 表达式、Context Valuer 创建记录

Customized Data Types , 示例如下:

// Create from map
db.Model(User{}).Create(map[string]interface{}{
"Name": "jinzhu",
"Location": clause.Expr{SQL: "ST_PointFromText(?)", Vars: []interface{}{"POINT(100 100)"}},
})
// INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText("POINT(100 100)"));

// Create from customized data type
type Location struct {
X, Y int
}

// Scan implements the sql.Scanner interface
func (loc *Location) Scan(v interface{}) error {
// Scan a value into struct from database driver
}

func (loc Location) GormDataType() string {
return "geometry"
}

func (loc Location) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return clause.Expr{
SQL: "ST_PointFromText(?)",
Vars: []interface{}{fmt.Sprintf("POINT(%d %d)", loc.X, loc.Y)},
}
}

type User struct {
Name string
Location Location
}

db.Create(&User{
Name: "jinzhu",
Location: Location{X: 100, Y: 100},
})
// INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText("POINT(100 100)"))

高级选项

关联创建

默认值

零值 插入到数据库中

注意 ,当结构体的字段默认值是零值的时候比如 0 , '' , false ,这些字段值将不会被保存到数据库中,你可以使用指针类型或者Scanner/Valuer来避免这种情况。

type User struct {
gorm.Model
Name string
Age *int `gorm:"default:18"`
Active sql.NullBool `gorm:"default:true"`
}

注意 ,若要让字段在数据库中拥有默认值则必须使用 default Tag来为结构体字段设置默认值。如果想要在数据库迁移的时候跳过默认值,可以使用 default:(-) ,示例如下:

type User struct {
ID string `gorm:"default:uuid_generate_v3()"` // db func
FirstName string
LastName string
Age uint8
FullName string `gorm:"->;type:GENERATED ALWAYS AS (concat(firstname,' ',lastname));default:(-);"`
}

注意 SQLite 不支持批量插入的时候使用默认值。 前往 SQLite Insert stmt 了解。 下面是一个使用案例:

type Pet struct {
Name string `gorm:"default:cat"`
}

// 在SqlLite中,这是不允许的, 所以GORM会通过构建错误的SQL来返回错误:
// INSERT INTO `pets` (`name`) VALUES ("dog"),(DEFAULT) RETURNING `name`
db.Create(&[]Pet{{Name: "dog"}, {}})

一个可行的替代方案是通过钩子方法来设置默认字段

func (p *Pet) BeforeCreate(tx *gorm.DB) (err error) {
if p.Name == "" {
p.Name = "cat"
}
}

你可以在 issues#6335 了解到更多有关信息。

当使用virtual/generated value时,你可能需要禁用它的创建/更新权限,前往 Field-Level Permission 了解字段权限。

Upsert 及冲突

Advanced Query 了解有关 FirstOrInit , FirstOrCreate 的信息。

查看 Raw SQL and SQL Builder 获取详情

入门指南 概述 声明模型 连接到数据库 GORM CLI The Generics Way CRUD 接口 创建 查询 高级查询 更新 删除 原生 SQL 和 SQL 生成器 关联 Belongs To Has One Has Many Many To Many Polymorphism 关联模式 预加载 教程 Context 错误处理 链式操作 Session 钩子 事务 迁移 Logger 通用数据库接口 性能 自定义数据类型 Scope 约定 设置 高级主题 Database Resolver Sharding Serializer Prometheus 提示 索引 约束 复合主键 安全 GORM 配置 编写插件 编写驱动 更新日志 社区 贡献 翻译当前页面 入门指南 概述 声明模型 连接到数据库 GORM CLI The Generics Way CRUD 接口 创建 查询 高级查询 更新 删除 原生 SQL 和 SQL 生成器 关联 Belongs To Has One Has Many Many To Many Polymorphism 关联模式 预加载 教程 Context 错误处理 链式操作 Session 钩子 事务 迁移 Logger 通用数据库接口 性能 自定义数据类型 Scope 约定 设置 高级主题 Database Resolver Sharding Serializer Prometheus 提示 索引 约束 复合主键 安全 GORM 配置 编写插件 编写驱动 更新日志 社区 贡献 翻译当前页面