我在一行中有大约20列,并且在创建行时也不需要填写所有列我也不想在SQL查询中的每个列的cardcode名称和前端的http.post请求上。所有值均来自表单。我的代码:
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)
有什么建议吗? 谢谢!
答案 0 :(得分:1)
我认为你的代码示例只是伪代码,但我会在明显的情况下陈述这些代码。
db.Query("insert into views (?,?,?,?,?,?) values (?,?,?,?,?,?)", colNames..., values...)
这是无效的Go因为你只能"解包"函数的最后一个参数,也是无效的MySQL,因为你不能使用占位符(?
)作为列名。
db.Query("insert into views " + colNames + " values" + values)
这也是无效的Go因为你不能用切片连接字符串。
您可以将切片格式化为如下所示的字符串:
colNamesString := "(col1, col2, col3)"
valuesString := "(val1, val2, val3)"
现在您的第二个代码示例变为有效Go并将编译但不执行此操作。如果您这样做,您的应用程序将容易受到SQL注入攻击,这就是您的意思绝对不想要。
而是做这样的事情:
// 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...)