いがにんのぼやき

WEBエンジニアのブログ。IT、WEB、バンド、アニメ。

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
}