Placeholder ('?'
) hanya dapat digunakan untuk menyisipkan nilai lolos dinamis untuk parameter filter (mis. di WHERE
bagian), di mana nilai data akan muncul, bukan untuk kata kunci SQL, pengidentifikasi, dll. Anda tidak dapat menggunakannya untuk menentukan ORDER BY
secara dinamis ATAU GROUP BY
nilai.
Anda masih dapat melakukannya, misalnya Anda dapat menggunakan fmt.Sprintf()
untuk merakit teks kueri dinamis seperti ini:
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Hal-hal yang perlu diingat:
Melakukannya, Anda harus mempertahankan secara manual vs injeksi SQL, mis. jika nilai nama kolom berasal dari pengguna, Anda tidak dapat menerima nilai apa pun dan hanya memasukkannya langsung ke kueri jika tidak, pengguna akan dapat melakukan segala macam hal buruk. Secara sepele, Anda hanya boleh menerima huruf alfabet Inggris + angka + garis bawah ('_'
).
Tanpa mencoba menyediakan fungsi checker atau escaping yang lengkap dan lengkap, Anda dapat menggunakan regexp sederhana ini yang hanya menerima huruf, angka, dan '_'
dalam bahasa Inggris :
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
Contoh (coba di Go Playground ):
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