使用sqlx执行插入操作时能否避免显式罗列表字段?
解决方案
sqlx本身没有内置这种自动生成插入语句的接口,你可以通过反射自行封装通用插入方法实现你要的效果,具体实现步骤如下:
1. 修正结构体标签定义
sqlx默认读取结构体的db标签获取字段映射关系,你之前把字段映射写到json标签里的写法不被sqlx识别,修正后的结构体定义如下:
type MyData struct { Field1 string `json:"field1" db:"field1"` Field2 string `json:"field2" db:"field2"` }
2. 封装通用插入方法
通过反射解析结构体的db标签和对应字段值,自动拼接SQL语句,示例代码如下:
import ( "database/sql" "errors" "fmt" "reflect" "strings" "github.com/jmoiron/sqlx" ) // Insert 通用单条插入方法 // 参数:db为sqlx实例,tableName为目标表名,data为存储插入数据的结构体实例/结构体指针 func Insert(db *sqlx.DB, tableName string, data interface{}) (sql.Result, error) { t := reflect.TypeOf(data) v := reflect.ValueOf(data) // 处理指针类型入参 if t.Kind() == reflect.Ptr { t = t.Elem() v = v.Elem() } // 校验入参类型必须是结构体 if t.Kind() != reflect.Struct { return nil, errors.New("data parameter must be a struct or struct pointer") } var columns []string var args []interface{} var placeholders []string for i := 0; i < t.NumField(); i++ { field := t.Field(i) dbTag := field.Tag.Get("db") // 跳过无db标签、标记为忽略的字段 if dbTag == "" || dbTag == "-" { continue } // 可选:跳过零值字段,不需要插入零值可以保留这段逻辑,需要插入零值就删除 fieldVal := v.Field(i).Interface() if reflect.DeepEqual(fieldVal, reflect.Zero(field.Type).Interface()) { continue } columns = append(columns, dbTag) args = append(args, fieldVal) placeholders = append(placeholders, "?") } // 拼接INSERT语句 sqlStr := fmt.Sprintf( "INSERT INTO %s (%s) VALUES (%s)", tableName, strings.Join(columns, ", "), strings.Join(placeholders, ", "), ) // 适配不同数据库的占位符格式(如PostgreSQL会自动将?转换为$1、$2格式) sqlStr = db.Rebind(sqlStr) // 执行SQL return db.Exec(sqlStr, args...) }
3. 调用示例
封装完成后就可以实现你想要的调用效果:
// 构造插入数据 data := MyData{ Field1: "test1", Field2: "test2", } // 调用通用插入方法 res, err := Insert(db, "your_table_name", data)
注意事项
- 上述示例仅实现了单条插入逻辑,你可以根据需要扩展批量插入、条件更新等通用方法
- 零值过滤逻辑可根据业务需求调整,如果需要插入零值(比如0、false、空字符串)直接删除对应的判断逻辑即可
内容的提问来源于stack exchange,提问作者daisy
相关产品推荐
相关产品推荐

