プレースホルダー('?'
)は、フィルタパラメータの動的なエスケープ値を挿入するためにのみ使用できます(例: WHERE
一部)、SQLキーワード、識別子などではなく、データ値が表示される場所。これを使用して、 ORDER BY
を動的に指定することはできません。 またはGROUPBY
値。
ただし、それでも実行できます。たとえば、 fmt.Sprintf()を使用できます。コード>
次のように動的クエリテキストを組み立てるには:
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
注意事項:
そうすることで、SQLインジェクションに対して手動で防御する必要があります。列名の値がユーザーからのものである場合、値を受け入れることはできず、クエリに直接挿入するだけです。そうしないと、ユーザーはあらゆる種類の悪いことを行うことができます。当然のことながら、英語のアルファベット+数字+アンダースコア('_'
)の文字のみを受け入れる必要があります 。
完全で包括的なチェッカーやエスケープ機能を提供しようとせずに、英語の文字、数字、および'_'
のみを受け入れるこの単純な正規表現を使用できます。 :
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
例( GoPlayground で試してみてください ):
fmt.Println(valid.MatchString("title")) // true
fmt.Println(valid.MatchString("another_col_2")) // true
fmt.Println(valid.MatchString("it's a trap!")) // false
fmt.Println(valid.MatchString("(trap)")) // false
fmt.Println(valid.MatchString("also*trap")) // false