gorm批量插入解决方案

简介: gorm批量插入解决方案

我有一个朋友, 最近用gorm发现官方不支持批量插入, 看官方issue 2014年就有人提过这个问题了, 不过现在还不支持


但是问题不大, 官方留出来一个执行原生SQL(db.Exec)的方法来解决这个问题, 而且官方现在在开发v2版本, 在v2版本中就会支持这个功能了


image.png


但是生活还得继续, bug还是得继续写, 本来想在网上找一个公用方法来维持一下生活, 结果竟然没找见!


20200415202812852.png


都是指定单个结构体去插入的


20200415203137638.png


这当然不行了, 写代码的意义不就是为了减轻重复的工作嘛, 既然这样, 就只能自己动手丰衣足食了

20200415203343988.png

下面为生成语句的方法

// GetBranchInsertSql 获取批量添加数据sql语句
func GetBranchInsertSql(objs []interface{}, tableName string) string {
  if len(objs) == 0 {
    return ""
  }
  fieldName := ""
  var valueTypeList []string
  fieldNum := reflect.TypeOf(objs[0]).NumField()
  fieldT := reflect.TypeOf(objs[0])
  for a := 0; a < fieldNum; a++ {
    name := GetColumnName(fieldT.Field(a).Tag.Get("gorm"))
    // 添加字段名
    if a == fieldNum-1 {
      fieldName += fmt.Sprintf("`%s`", name)
    } else {
      fieldName += fmt.Sprintf("`%s`,", name)
    }
    // 获取字段类型
    if fieldT.Field(a).Type.Name() == "string" {
      valueTypeList = append(valueTypeList, "string")
    } else if strings.Index(fieldT.Field(a).Type.Name(), "uint") != -1 {
      valueTypeList = append(valueTypeList, "uint")
    } else if strings.Index(fieldT.Field(a).Type.Name(), "int") != -1 {
      valueTypeList = append(valueTypeList, "int")
    }
  }
  var valueList []string
  for _, obj := range objs {
    objV := reflect.ValueOf(obj)
    v := "("
    for index, i := range valueTypeList {
      if index == fieldNum-1 {
        v += GetFormatField(objV, index, i, "")
      } else {
        v += GetFormatField(objV, index, i, ",")
      }
    }
    v += ")"
    valueList = append(valueList, v)
  }
  insertSql := fmt.Sprintf("insert into `%s` (%s) values %s", tableName, fieldName, strings.Join(valueList, ",")+";")
  return insertSql
}
// GetFormatField 获取字段类型值转为字符串
func GetFormatField(objV reflect.Value, index int, t string, sep string) string {
  v := ""
  if t == "string" {
    v += fmt.Sprintf("'%s'%s", objV.Field(index).String(), sep)
  } else if t == "uint" {
    v += fmt.Sprintf("%d%s", objV.Field(index).Uint(), sep)
  } else if t == "int" {
    v += fmt.Sprintf("%d%s", objV.Field(index).Int(), sep)
  }
  return v
}
// GetColumnName 获取字段名
func GetColumnName(jsonName string) string {
  for _, name := range strings.Split(jsonName, ";") {
    if strings.Index(name, "column") == -1 {
      continue
    }
    return strings.Replace(name, "column:", "", 1)
  }
  return ""
}
// BatchCreateModelsByPage 分页批量插入
func BatchCreateModelsByPage(tx *gorm.DB, dataList []interface{}, tableName string) (err error) {
  if len(dataList) == 0 {
    return
  }
  // 如果超过一百条, 则分批插入
  size := 100
  page := len(dataList) / size
  if len(dataList)%size != 0 {
    page += 1
  }
  for a := 1; a <= page; a++ {
    var bills = make([]interface{}, 0)
    if a == page {
      bills = dataList[(a-1)*size:]
    } else {
      bills = dataList[(a-1)*size : a*size]
    }
    sql := GetBranchInsertSql(bills, tableName)
    if err = tx.Exec(sql).Error; err != nil {
      fmt.Println(fmt.Sprintf("batch create data error: %v, sql: %s, tableName: %s", err, sql, tableName))
      return
    }
  }
  return
}

最后会返回批量插入的sql语句, 这样一来就舒服多了

因为我的朋友 现在类型主要用到了string, int和uint, 如果有其他类型需要加的话在 获取字段类型和GetFormatFeild里面加就行了

如果各位大佬有更好的解决方案希望可以拿出来分享学习一下

20200415202716469.png

目录
相关文章
|
6月前
|
SQL 数据库 索引
gorm普通的增删改查
gorm普通的增删改查
64 0
|
2月前
|
关系型数据库 MySQL 数据库
MySQL 表的CRUD与复合查询
【9月更文挑战第26天】本文介绍了数据库操作中的 CRUD(创建、读取、更新、删除)基本操作及复合查询。创建操作使用 `INSERT INTO` 语句插入数据,支持单条和批量插入;读取操作使用 `SELECT` 语句查询数据,可进行基本查询、条件查询和排序查询;更新操作使用 `UPDATE` 语句修改数据;删除操作使用 `DELETE FROM` 语句删除数据。此外,还介绍了复合查询,包括连接查询(如内连接、左连接)和子查询,以及聚合函数与分组查询,并提供了示例代码。
|
3月前
|
SQL 关系型数据库 MySQL
解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
|
5月前
|
SQL Go 数据库
Go语言之GORM框架(二) ——GORM的单表操作
Go语言之GORM框架(二) ——GORM的单表操作
|
6月前
|
Go
golang使用gorm操作mysql3,数据查询
golang使用gorm操作mysql3,数据查询
|
11月前
|
SQL 关系型数据库 MySQL
mysql单条sql批量更新封装
mysql单条sql批量更新封装
87 1
|
SQL Oracle 关系型数据库
|
SQL 安全 数据库
GORM V2 写操作
GORM V2 写操作
52 0
|
Go
GORM v2 一对一关联查询使用(Belongs To 、Has One)
GORM v2 一对一关联查询使用(Belongs To 、Has One)
420 0
GORM v2 一对一关联查询使用(Belongs To 、Has One)
|
SQL 缓存 搜索推荐
Gorm学习(三)基础:迁移(数据库建表以及字段设置)
在项目开发中,我们可能会随时调整声明的模型,比如添加字段和索引,使用 GORM 的自动迁移功能,可以始终让我们的数据库表结构保持最新。
1169 0
Gorm学习(三)基础:迁移(数据库建表以及字段设置)