Pré-construindo a consulta SQL (evitando injeção de SQL)
Se você estiver gerando uma string SQL com um placeholder param para cada um dos valores, é mais fácil gerar o SQL final imediatamente.
Observe que, como os valores são
string
s, há lugar para o ataque de injeção de SQL, então primeiro testamos se todas as string
os valores são de fato números, e só procedemos se assim for: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(")")
Executando:
num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
log.Println(err)
}
Usando ANY
Você também pode usar o
ANY
do Postgresql , cuja sintaxe é a seguinte:expression operator ANY (array expression)
Usando isso, nossa consulta pode ficar assim:
SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])
Nesse caso, você pode declarar o formato de texto do array como parâmetro:
SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])
Que pode ser simplesmente construído assim:
tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"
Observe que nenhuma verificação é necessária neste caso, pois a expressão de matriz não permitirá injeção de SQL (mas resultará em um erro de execução de consulta).
Então o código completo:
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)
}