Предварително изграждане на SQL заявката (предотвратяване на SQL инжектиране)
Ако генерирате SQL низ с заместващ параметър за всяка от стойностите, по-лесно е просто да генерирате окончателния SQL веднага.
Имайте предвид, че тъй като стойностите са string
s, има място за атака с инжектиране на SQL, така че първо тестваме дали целият string
стойностите наистина са числа и ние продължаваме само ако е така:
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)
}
Използване на ANY
Можете също да използвате ANY
на Postgresql , чийто синтаксис е както следва:
expression operator ANY (array expression)
Използвайки това, нашата заявка може да изглежда така:
SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])
В този случай можете да декларирате текстовата форма на масива като параметър:
SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])
Което може просто да се изгради така:
tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"
Имайте предвид, че в този случай не се изисква проверка, тъй като изразът на масива няма да позволи 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(&num); err != nil {
log.Println(err)
}