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



有人能向我解释为什么这不起作用吗?

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)

我正在尝试用一片int做一个简单的IN子句,并且所建议的每个解决方案似乎都不是很地道

尝试过这样做,但问题似乎是字符串替换。

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

我有点惊讶的是,go似乎没有一种优雅的方式来处理这个查询。

因为数据库/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包来处理这些类型的查询,该包提供了对数据库查询的更多控制。

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

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

有关更多信息,请访问Godoc For InQueries

如果你一直很小心地从真正的int构建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。不过,请注意您接受的参数,就像您接受任意字符串一样,任何东西都可以注入。

您需要"quot;在";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)

我刚刚遇到了同样的问题,然后我想出了另一个更安全的解决方案。因此,您不需要知道SQL注入。

params := []string{"A", "B"}
jsonParams, err := json.Marshal(params)
if err != nil {
return err
}
rows, err = db.Query(`
WITH compared_values as(
SELECT * 
FROM JSON_TABLE(
?,
"$[*]" COLUMNS( 
value TEXT PATH "$"
)
) as compared_values
) 
SELECT * FROM target_table
WHERE target_value IN (SELECT value FROM compared_values);
`, jsonParams)

您也可以像这样在SQL查询中使用纯选择部分,但我不确定性能。我认为使用WITH原因可以防止重复的JSON解析。

SELECT * FROM  target_table
WHERE target_value IN (
SELECT value FROM JSON_TABLE(
?,
"$[*]" COLUMNS( 
value TEXT PATH "$"
)
) as compared_values
);

最新更新