Go and IN clause in Postgres

前端 未结 2 1838
傲寒
傲寒 2020-11-27 07:32

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)

2条回答
  •  轮回少年
    2020-11-27 07:59

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

提交回复
热议问题