postgresql – Postgres中的Go和IN子句

前端之家收集整理的这篇文章主要介绍了postgresql – Postgres中的Go和IN子句前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图使用 pq driver对Go中的Postgresql数据库执行以下查询
SELECT COUNT(id)
FROM tags
WHERE id IN (1,2,3)

其中1,3在切片标签处传递:= [] string {“1”,“2”,“3”}.

我尝试了很多不同的东西,比如:

s := "(" + strings.Join(tags,",") + ")"
if err := Db.QueryRow(`
    SELECT COUNT(id)
    FROM tags
    WHERE id IN $1`,s,).Scan(&num); err != nil {
    log.Println(err)
}

这导致pq:语法错误在“$1”或附近.我也试过了

if err := Db.QueryRow(`
    SELECT COUNT(id)
    FROM tags
    WHERE id IN ($1)`,strings.Join(stringTagIds,"),).Scan(&num); err != nil {
    log.Println(err)
}

这也失败了pq:整数的输入语法无效:“1,3”

我也尝试直接传递一片整数/字符串并得到sql:转换Exec参数#0的类型:不支持的type []字符串,一个切片.

那么如何在Go中执行此查询

预构建SQL查询(防止sql注入)

如果您为每个值生成带有param占位符的sql字符串,则可以更轻松地立即生成最终sql.

请注意,由于值是字符串,因此存在sql注入攻击的位置,因此我们首先测试所有字符串值是否确实是数字,我们只在这样做:

tags := []string{"1","2","3"}
buf := bytes.NewBufferString("SELECT COUNT(id) FROM tags WHERE id IN(")
for i,v := range tags {
    if i > 0 {
        buf.WriteString(",")
    }
    if _,err := strconv.Atoi(v); err != nil {
        panic("Not number!")
    }
    buf.WriteString(v)
}
buf.WriteString(")")

执行它:

num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
    log.Println(err)
}

使用任何

您也可以使用Postgresql’s ANY,其语法如下:

expression operator ANY (array expression)

使用它,我们的查询可能如下所示:

SELECT COUNT(id) FROM tags WHERE id = ANY('{1,3}'::int[])

在这种情况下,您可以将数组的文本形式声明为参数:

SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])

这可以简单地像这样构建:

tags := []string{"1","3"}
param := "{" + strings.Join(tags,") + "}"

请注意,在这种情况下不需要检查,因为数组表达式不允许sql注入(但会导致查询执行错误).

那么完整的代码

tags := []string{"1","3"}

q := "SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])"
param := "{" + strings.Join(tags,") + "}"

num := 0
if err := Db.QueryRow(q,param).Scan(&num); err != nil {
    log.Println(err)
}

猜你在找的Postgre SQL相关文章