使用slice IN子句的Golang数据库查询

时间:2018-07-26 12:18:32

标签: sql go slice

有人可以向我解释为什么这行不通吗?

inq := "6,7" //strings.Join(artIds, ",")
rows, err = db.Query("SELECT DISTINCT title FROM tags_for_articles LEFT JOIN tags ON tags.id = tags_for_articles.tag_id WHERE article_id IN (?)", inq)

这是

rows, err = db.Query("SELECT DISTINCT title FROM tags_for_articles LEFT JOIN tags ON tags.id = tags_for_articles.tag_id WHERE article_id IN (6,7)", inq)

我正在尝试使用一个整数切片来执行一个简单的IN子句,并且建议的每种解决方案似乎都不是惯用语

试图这样做,但是问题似乎出在字符串替换上。

inq := strings.Join(artIds, ",")

我对go似乎没有一种优雅的方式来处理此查询感到惊讶。

3 个答案:

答案 0 :(得分:1)

  

因为数据库/ sql不检查您的查询,并且它通过您   参数直接传递给驱动程序,它使处理查询   IN子句很困难:

SELECT * FROM users WHERE level IN (?);
  

当这准备好作为后端的语句时,bindvar?   只对应一个参数,但是通常需要   是因为它是可变数量的参数,具体取决于   一些切片的长度

var levels = []int{4, 6, 7}
rows, err := db.Query("SELECT * FROM users WHERE level IN (?);", levels)

有一种使用sqlx package处理这些类型的查询的方法,它可以更好地控制数据库查询。

可以通过首先使用sqlx.In处理查询来实现此模式。

var levels = []int{4, 6, 7}
query, args, err := sqlx.In("SELECT * FROM users WHERE level IN (?);", levels)

有关更多信息,请通过Godoc获得InQueries

答案 1 :(得分:1)

如果您一直很小心地从实数整数构建inq字符串(以避免注入),则可以自己构建字符串并避免使用?:

inq := "6,7" 
sql := fmt.Sprintf("SELECT DISTINCT title FROM tags_for_articles LEFT JOIN tags ON tags.id = tags_for_articles.tag_id WHERE article_id IN (%s)",inq)
rows, err := db.Query(sql)

如果您经常这样做,最好有一个WhereIn函数为您执行此操作,或者使用orm。但是要小心接受哪些参数,就像接受任意字符串一样。

答案 2 :(得分:0)

您需要“?”的数量在“IN”子句中匹配参数的数量,所以你需要做这样的事情:

inq := "6,7" //strings.Join(artIds, ",")
qms := strings.Repeat("?,", len(inq))
qms = params[:len(params)-1] // remove the trailing ","

rows, err = db.Query("SELECT DISTINCT title FROM tags_for_articles LEFT JOIN tags ON tags.id = tags_for_articles.tag_id WHERE article_id IN (" + qms + ")", inq)