【问题标题】:Build dynamic (conditional) WHERE SQL query in Golang在 Golang 中构建动态(条件)WHERE SQL 查询
【发布时间】:2021-08-20 10:38:06
【问题描述】:

我正在使用 golang、go_reform、PostgreSQL。我想做的是一个 REST 搜索实用程序,在我遇到条件搜索查询之前一切都很好。这里的“条件”意味着我在一个表中有 10 列要搜索,并且可能有很多组合,所以我不能单独处理它们。我需要的是一个查询构建器,但我不知道如何在 Go 中实现它。目前我有这样的想法,但似乎效率不高

type Query struct {
    Id               *int64
    FirstName        *string
    MiddleName       *string
    LastName         *string
    AreaId           *int64
    Birthday         *time.Time
}

func (table *Query) Find() (*User) {
    if table.Id != nil {
        idstr := fmt.Sprintf("WHERE Id = %d AND ", table.Id)
    }
    else idstr := "WHERE "
    }
    if table.FirstName != "" {
        firststr := fmt.Sprintf("FirstName = %s AND", table.FirstName)
    }
    else firststr := ""
}//and so on

感觉真的很尴尬,所以我想知道是否有更好的方法来确定 Find() 的字段并基于此构建 SQL 查询。 (实际上它以 JSON 形式出现并绑定到Query struct,所以也许有一种没有 struct 的方法)。也可能有 SQL 解决方法,但我认为在没有所有可能列的情况下构建查询会更有效。

编辑:顺便说一句,为了让我的谷歌搜索查询更准确,我发现了一堆与我的问题相关的东西,可能我现在会尝试使用它。对于那些也有兴趣的人: old go playground example

Making dynamic SQL queries to a MySQL DB

gorp package(sn-ps 的东西听起来很有前途)

【问题讨论】:

  • 除了编译错误(即elector.FirstName是一个指针,所以不能与字符串比较)之外,这是一个合理的方法。
  • 不要使用 fmt 动词(字符串中的 %d, %s 等)来构建查询,您正在为一些 sql 注入做准备。
  • 我对 ORM 的看法是,它们使本来很简单的任务变得更容易,而复杂的任务变得不可能。我认为它们是邪恶的,应该始终避免,没有例外。我的观点并不总是受欢迎,但这是我的观点。
  • @PavelNasevich 如果你不介意使用反射,你可以这样做:play.golang.org/p/BlADhht9PwO
  • @EliasVanOotegem:ORM 本身并不是我们所需要的。查询构建器是。 ORM 通常将这些作为特性包含在内,但没有理由需要 ORM 来获得该特性。

标签: go orm printf


【解决方案1】:

所以,我找到了解决方案。非常感谢Cerise Limón,他的代码非常适合我。

我最终得到的解决方案

控制器

func Find(c echo.Context) (err error) {
model := &models.Query{}
if err = c.Bind(model); err != nil {
    return c.JSON(http.StatusInternalServerError, u.Message(false, "Bad request"))
}
resp := model.Find()
return c.JSON(http.StatusOK, resp)

型号

type Query map[string]interface{}

func (model Query) Find() (Query) {
    var values []interface{}
    var where []string
    for k, v := range model {
        values = append(values, v)
        //MySQL Way: where = append(where, fmt.Sprintf("%s = ?", k))
        where = append(where, fmt.Sprintf(`"%s" = %s`,k, "$" + strconv.Itoa(len(values))))
    }
    string := ("SELECT name FROM users WHERE " + strings.Join(where, " AND "))
    //for testing purposes i didn't ran actual query, just print it in the console and returned JSON back
    fmt.Println(string)
    return model

}

更新:对于 PostgreSQL 用户(感谢 @mkopriva 和他的 playground example),我可以让这个占位符在 PostgreSQL 上正常工作

【讨论】:

  • 基本上,我还有一个小问题——我用的是PostgreSQL,所以占位符“?”在这里是不行的,我不知道如何将其替换为 1 美元、2 美元等。
  • 这会让你对 SQL 注入持开放态度,不是吗?你在哪里净化你的价值观?
  • 这不容易受到 SQL 注入的影响,因为占位符用于应用程序直接控制之外的部分查询。
【解决方案2】:

在 orm GORM 中,我们这样做

if con1 {
    db.Where("con1 =?", con1Flag)
}

如果是你自己写的orm,我建议改成gorm。或者你可以参考你正在使用的orm,是否和上面的代码有相同的用法。 如果您自己编写代码,请随心所欲。 如果你在小组中工作,我想使用成熟的 orm 会更好

【讨论】:

    【解决方案3】:

    在 PostgreSQL 中

    查询(字符串 sql, args...)

    当我在表单中将值传递给 Query 时 查询(字符串,值) 只添加一个值,预期应该是2,接口数组应该如何作为args传递给Query

    我找到了答案:您需要将其作为 Query(string, values...) 传入

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-06
      • 2015-01-30
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多