sqlxでIN句を使う方法
最近Goでsqlxを使っているが、毎回忘れるのでメモ
IN句を用いたクエリ
sqlxでIN句を用いたクエリを使うにはそのままクエリを投げることはできない。
一度 sqlx.In を通してあげる必要がある。
type Hoge struct { Id string `db:"id"` } db, err := sqlx.Connect("mysql", "接続情報") if err != nil { panic(err) } query := ` SELECT id FROM hoge WHERE id IN (?) ` idList := []string{"aaa", "bbb", "ccc"} // 一度sqlx.Inを通してあげる必要がある query, args, err := sqlx.In(query, idLIst) if err != nil { panic(err) } // DBのドライバーに合わせたクエリの変換 query = db.Rebind(query) var result []*Hoge err = db.Select(&result, query, args...) if err != nil { panic(err) } return result
Selectの結果を別に詰め替えるなら
// 上の結果がresult変数に入っているとして type Fuga struct { Id string } // 結果の長さ文の容量を確保したスライスを用意 newResult := make([]*Fuga, 0, len(result)) for _, r := range result { newResult = append(newResult, &Fuga{Id: r.Id}) } return newResult
ここらへんのappendがGo特有というかLLやJavaといった言語ではあまり見ないやり方
IN句に指定する値以外にバインドが必要な場合
SQLに :idList
のように名前を指定して値をバインドでき、それはもちろんIN句との併用も可能
以下のようにsqlx.Inとsqlx.Namedを組み合わせてクエリを組み立てていく
type Hoge struct { Id string `db:"id"` } db, err := sqlx.Connect("mysql", "接続情報") if err != nil { panic(err) } query := ` SELECT id FROM hoge WHERE id IN (:idList) AND data_type = :dataType ` idList := []string{"aaa", "bbb", "ccc"} dataType := "xxxType" input := map[string]interface{}{ "idList": idList, "dataType": dataType, } // 最初にsqlx.Named query, args, err := sqlx.Named(query, input) // 次にsqlx.In query, args, err := sqlx.In(query, args...) if err != nil { panic(err) } query = db.Rebind(query) var result []*Hoge err = db.Select(&result, query, args...) if err != nil { panic(err) } return result
決まった手続きなので以下のようなラッパー関数を作ってもいいかもしれない
func NamedInSql(db sqlx.DB, query string, arg interface{}) (string, []interface{}, error) { query, args, err := sqlx.Named(query, arg) if err != nil { return "", nil, err } query, args, err = sqlx.In(query, args...) if err != nil { return "", nil, err } query = db.Rebind(query) return query, args, err }