sqlxでIN句を含むクエリをNamedStmtで扱う方法のサンプルコードです。
EXISTS句にも応用可能です。
サンプルコード
main.go
func main() {
userIds := []int{1, 2, 3, 4, 5}
age := 20
select(ids, createdAt)
}
select.go
var db *sqlx.DB
func select(userIds []int, age int) ([]User, error) {
// SQLの雛形
originQuery := `SELECT * FROM USER WHERE USER_ID IN (:USER_ID) AND AGE > :AGE`
// バインドする値
arg := map[string]interface{}{
"USER_ID": userIds,
"AGE": age,
}
// NamedStmtでIN句を使える形式にする
query, params := formatQuery(&originQuery, &arg)
// Select文を実行
namedStmt, err := db.PrepareNamedContext(context.Background(), *query)
if err != nil {
return nil, err
}
defer namedStmt.Close()
var users []User
if err := namedStmt.SelectContext(context.Background(), &sqlxSamples, *params); err != nil {
return nil, err
}
return users, nil
}
format.go
func formatQuery(q *string, a *map[string]interface{}) (*string, *map[string]interface{}) {
query, args, _ := sqlx.Named(*q, *a)
fmt.Println(query) // SELECT * FROM USER WHERE USER_ID IN (?) AND AGE > ?
fmt.Println(args) // [[1 2 3 4 5] 20]
query, args, _ = sqlx.In(query, args...)
fmt.Println(query) // SELECT * FROM USER WHERE USER_ID IN (?, ?, ?, ?, ?) AND AGE > ?
fmt.Println(args) // [1 2 3 4 5 20]
query = sqlx.Rebind(sqlx.NAMED, query)
params := map[string]interface{}{}
for i, arg := range args {
key := fmt.Sprintf("arg%d", i+1)
params[key] = arg
}
fmt.Println(query) // SELECT * FROM USER WHERE USER_ID IN (:arg1, :arg2, :arg3, :arg4, :arg5) AND AGE > :arg6
fmt.Println(params) // map[arg1:1 arg2:2 arg3:3 arg4:4 arg5:5 arg6:20]
return &query, ¶ms
}