在Postgres中执行IN子句 [英] Go and IN clause in Postgres

查看:288
本文介绍了在Postgres中执行IN子句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 pq驱动程序在Go中对PostgreSQL数据库执行以下查询:

  SELECT COUNT(id)
FROM tags
WHERE id IN(1,2,3)

其中 1,2,3 tags:= [] string {1,2,3}



尝试了许多不同的东西,例如:

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

其中导致 pq:语法错误处于或接近$ 1。我也试过如果err:= Db.QueryRow(`
SELECT COUNT(id)
FROM

 标签
WHERE id IN($ 1)`,strings.Join(stringTagIds,,),
).Scan(#)。 err!= nil {
log.Println(err)
}

其中也无法使用 pq:整数无效输入语法:1,2,3



直接切片整数/字符串并得到 sql:转换Exec参数#0的类型:不支持的类型[]字符串,切片



那么我该如何在Go中执行这个查询?

解决方案

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



如果您为每个值生成一个带有param占位符的SQL字符串,那么只需立即生成最终的SQL就会更容易。 b
$ b

请注意,由于值是 string s,因此存在SQL注入攻击的位置,所以我们首先测试是否所有的 string 的值确实是数字,我们只在这样的情况下继续:

  tags:= []字符串{1,2,3} 
buf:= bytes.NewBufferString(SELECT COUNT(id)FROM tags WHERE id IN()
for i,v:=范围标签{
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(#include); err!= nil {
log.Println(err)
}



使用 ANY



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

 表达式运算符ANY(数组表达式)



<我们的查询可能如下所示:

1,2,3}':: int [])

在这种情况下,您可以声明文本

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

可以像这样简单地构建:

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

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



所以完整的代码:

  tags:= [] string {1,2,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(#); err!= nil {
log.Println(err)
}


I am trying to execute the following query against the PostgreSQL database in Go using pq driver:

SELECT COUNT(id)
FROM tags
WHERE id IN (1, 2, 3)

where 1, 2, 3 is passed at a slice tags := []string{"1", "2", "3"}.

I have tried many different things like:

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)
}

which results in pq: syntax error at or near "$1". I also tried

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

which also fails with pq: invalid input syntax for integer: "1,2,3"

I also tried passing a slice of integers/strings directly and got sql: converting Exec argument #0's type: unsupported type []string, a slice.

So how can I execute this query in Go?

解决方案

Pre-building the SQL query (preventing SQL injection)

If you're generating an SQL string with a param placeholder for each of the values, it's easier to just generate the final SQL right away.

Note that since values are strings, there's place for SQL injection attack, so we first test if all the string values are indeed numbers, and we only proceed if so:

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(")")

Executing it:

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

Using ANY

You can also use Postgresql's ANY, whose syntax is as follows:

expression operator ANY (array expression)

Using that, our query may look like this:

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

In this case you can declare the text form of the array as a parameter:

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

Which can simply be built like this:

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

Note that no check is required in this case as the array expression will not allow SQL injection (but rather will result in a query execution error).

So the full code:

tags := []string{"1", "2", "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)
}

这篇关于在Postgres中执行IN子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆