SQLクエリの事前構築(SQLインジェクションの防止)
各値のparamプレースホルダーを使用して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
の使用
PostgresqlのANY
を使用することもできます 、構文は次のとおりです:
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)
}