如何使用参数化查询按名称搜索列?

How can I use a parameterized query to search on a column by its name?

我的用户应该能够通过在输入框中输入搜索词并从下拉框中选择他们想要搜索的列来搜索数据库。

但是,我找不到在 golang 中参数化查询以使列名被识别为列名而不是值的方法。让我举个例子:

rows, err := db.Query("SELECT * FROM mytable WHERE ? = ?", col, searchStr)

我打开了 MySQL 日志记录,结果查询如下:

   41 Execute   SELECT *
    FROM mytable 
    WHERE 'Username' = 'Foo'

显然 Username 不应该用单引号引起来。

如何参数化此查询?我是否必须编写应用程序逻辑来检查每个查询的正确列名并使用字符串操作将列名添加到查询中(可能使用一些占位符字符来查找和替换)?

这试图帮助您避免错误的 args(防止 SQL 注入之类的事情),但并非旨在对值以外的任何内容进行替换。您希望它插入一个 table 名称。不幸的是,代码知道 col 的类型(字符串)并引用它,因为在 SQL 中它是 nvarchar 并且这就是它们文字的编写方式,用单引号引起来。可能看起来有点像 hack,但你需要这个;

db.Query(fmt.Sprintf("SELECT * FROM mytable WHERE %s = ?", col), searchStr)

在将 table 名称传递给 Query 之前将其放入您的查询字符串中,这样它就不会被视为参数(即在 where 子句中使用的值)。

你应该看看这个包裹。 https://github.com/gocraft/dbr

它非常适合您想做的事情。

import "github.com/gocraft/dbr"

// Simple data model
type Suggestion struct {
    Id        int64
    Title     string
    CreatedAt dbr.NullTime
}

var connection *dbr.Connection

func main() {

    db, _ := sql.Open("mysql","root@unix(/Applications/MAMP/tmp/mysql/mysql.sock)/dbname")
    connection = dbr.NewConnection(db, nil)
    dbrSess := connection.NewSession(nil)

    // Get a record
    var suggestion Suggestion
    err := dbrSess.Select("id, title").From("suggestions").
        Where("id = ?", 13).
        LoadStruct(&suggestion)

    if err != nil {
             fmt.Println(err.Error())
    } else {
             fmt.Println("Title:", suggestion.Title)
    }
}