我在一行中有大约 20 列,并且在创建行时并非所有列都需要填写,我也不想在 SQL 查询和前端的 http.post 请求中对每一列的名称进行卡片编码。所有的值(value)都来自形式。我的代码:
var colNames, values []string
for k, v := range formData {
colNames = append(colNames, k)
values = append(values, v)
}
现在我有 2 个数组:一个包含列名,第二个包含要插入的值。我想做这样的事情:
db.Query("insert into views (?,?,?,?,?,?) values (?,?,?,?,?,?)", colNames..., values...)
或者像这样:
db.Query("insert into views " + colNames + " values" + values)
有什么建议吗? 谢谢!
最佳答案
我假设您的代码示例只是伪代码,但为了以防万一,我会陈述显而易见的内容。
db.Query("insert into views (?,?,?,?,?,?) values (?,?,?,?,?,?)", colNames..., values...)
这是无效的 Go,因为你只能“解压”函数的最后一个参数,也是无效的 MySQL,因为你不能使用占位符 (?
) 作为列名。
db.Query("insert into views " + colNames + " values" + values)
这在 Go 中也是无效的,因为你不能将字符串与 slice 连接起来。
您可以将 slice 从 at 转换为如下所示的字符串:
colNamesString := "(col1, col2, col3)"
valuesString := "(val1, val2, val3)"
现在您的第二个代码示例变为有效的 Go 并且可以编译但不要这样做。如果您这样做,您的应用程序将容易受到 SQL 注入(inject)的攻击,这是您绝对不希望发生的事情。
而是做这样的事情:
// this can be a package level global and you'll need
// one for each table. Keep in mind that Go maps that
// are only read from are safe for concurrent use.
var validColNames = map[string]bool{
"col1": true,
"col2": true,
"col3": true,
// ...
}
// ...
var colNames, values []string
var phs string // placeholders for values
for k, v := range formData {
// check that column is valid
if !validColNames[k] {
return ErrBadColName
}
colNames = append(colNames, k)
values = append(values, v)
phs += "?,"
}
if len(phs) > 0 {
phs = phs[:len(phs)-1] // drop the last comma
}
phs = "(" + phs + ")"
colNamesString := "(" + strings.Join(colNames, ",") + ")"
query := "insert into views " + colNamesString + phs
db.Query(query, values...)
关于sql - 如何从数组中动态生成 SQL 查询列名和值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47113755/