Sqlx: Support for building dynamic queries?

Created on 19 Jun 2015  路  5Comments  路  Source: jmoiron/sqlx

Is there any builtin support to build e.g. dynamic UPDATE queries?
I found the sqlx.Named function which is able to take a map and assign the values according to the keys in the query, but is it possible with sqlx to build a (whole) query based on a given map?

Currently I'm building the query this way:

...

params := map[string]interface{}{
    "name": "John",
    "age":32,
}

named := make([]string, 0, len(params))
for key := range params {
  named = append(named, fmt.Sprintf("%s=:%s", key, key))
}
params["id"] = 232

result, err := db.NamedExec(fmt.Sprintf("UPDATE users SET %s WHERE id=:id;", strings.Join(named, ", ")), params)

...

Many thanks for your help...

All 5 comments

I've tried to mostly stay out of the business of building queries because

  1. I suspect that's an orthogonal concern
  2. There are other packages devoted entirely to it
  3. It seems opinionated enough what goes into it where choice would be good

The code above is fine; it's a pretty small utility function whose behavior is very straight forward.

I recommend https://github.com/lann/squirrel for this

I can second squirrel, and there are likely other packages that will focus on this in future.

I just met this problem and solved it. Below is my solution, hope help you.
You can use go variadic parameter: A parameter type prefixed with three dots (...) is called a variadic parameter.
Here is the dynamic select query spired me: https://stackoverflow.com/questions/46859705/making-dynamic-queries-in-golang-and-mysql
As the dynamic update query, well, string concat will help. Here is the code:

`func (um UserMapper) updateAUserInfo(res http.ResponseWriter, req *http.Request){
decoder := json.NewDecoder(req.Body)
var user User
err := decoder.Decode(&user)
if err != nil{
panic(err)
}
// EXMP: "email = '%s', name = '%s', password = '%s'"
var params string
//EXMP: "[email protected]", "hly
", "hly*"
var values []interface{}
v := reflect.ValueOf(user)
for i := 0; i < v.NumField(); i++{
key := v.Type().Field(i).Name
value := v.Field(i).Interface()
if value != "" && value != nil && key != "CreatedAt" && key != "ID"{
kString := key + "='%s'"
params = kString + "," + params
values = append(values, value)
}
}
params = params[:(len(params)-1)]
updatedUser, err := um.updateUserInfo(params, values, user.ID)
fmt.Fprintf(res, "updated info are: %v", updatedUser)

}`

And the updateUserInfo function will be:
func (um *UserMapper) updateUserInfo(params string, values []interface{}, id string) (*User, error) { u := &User{} paramString := "UPDATE users set " + params err := um.DB.QueryRow(fmt.Sprintf(fmt.Sprintf(paramString, values...) + fmt.Sprintf(" where id = '%s'", id) )) if err != nil{ log.Fatal(err) } return u, nil }

The point is how to concat the values... and id value, I concat the two fmt.Sprintf() to solved =>
err := um.DB.QueryRow(fmt.Sprintf(fmt.Sprintf(paramString, values...) + fmt.Sprintf(" where id = '%s'", id) ))
Hope help you.

@YangShuting please use appropriate use of markdown https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code

Was this page helpful?
0 / 5 - 0 ratings