一尘不染

Golang ORDER BY问题与MySql

mysql

我似乎无法与db.Select()动态进行ORDER BY。我已经没有任何运气谷歌了…

作品

rows, err := db.Query("SELECT * FROM Apps ORDER BY title DESC")

不起作用

rows, err := db.Query("SELECT * FROM Apps ORDER BY ? DESC", "title")

我没有收到任何错误,查询只是无法排序。


阅读 582

收藏
2020-05-17

共1个答案

一尘不染

占位符('?')仅可用于为WHERE应在其中显示数据值的过滤器参数(例如,在零件中)插入动态的转义值,而不能用于SQL关键字,标识符等。您不能使用它来动态指定ORDER BYOR GROUP BY值。

不过,您仍然可以执行此操作,例如,可以使用以下方式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
}

示例(在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
2020-05-17