我以前从未将golang与mysql一起使用,因此我是第一次阅读这些内容。我想做这样的事情:
if userId && gender && age db.QueryRow("SELECT name FROM users WHERE userId=? AND gender=? AND age=?", userId,gender,age) else if gender && age db.QueryRow("SELECT name FROM users WHERE gender=? AND age=?", gender, age) else if userId && gender db.QueryRow("SELECT name FROM users WHERE userId=? AND gender=?", userId,gender) else if userId && age db.QueryRow("SELECT name FROM users WHERE userId=? AND age=?", userId, age) else if gender db.QueryRow("SELECT name FROM users WHERE gender=?", gender) else if userId db.QueryRow("SELECT name FROM users WHERE userId=?", userId) else if age db.QueryRow("SELECT name FROM users WHERE age=?", age)
这种输入太多了,特别是如果我想将更多变量添加到WHERE条件中时。
如果这是PHP,我将执行以下操作:
$sql = "SELECT name FROM users "; $where = array(); foreach(explode(",","userId,gender,age,name,height,weight,ethnicity" as $field) { if(isset($arrayOfValues[$field])) { $where[count($where)] = $field." = ?".$field $db->bind("?".$field,$arrayOfValues[$field]); } } if(count($where)>0) $sql = $sql . " WHERE ".implode(" AND ",$where); $db->query($sql);
通过使用foreach循环,我可以动态生成查询并根据需要动态绑定尽可能多的变量。
像golang和mysql这样的选项吗?还是有一些替代方案,可以不为查询输入每个变量组合?
如果您的地图具有这样的字段名称和值:
m := map[string]interface{}{"UserID": 1234, "Age": 18}
那么您可以像这样构建查询:
var values []interface{} var where []string for _, k := range []string{"userId", "gender", "age", "name", "height", "weight", "ethnicity"} { if v, ok := m[k]; ok { values = append(values, v) where = append(where, fmt.Sprintf("%s = ?", k)) } } r, err := db.QueryRow("SELECT name FROM users WHERE " + strings.Join(where, " AND "), values...)
这不会受到SQL注入的影响,因为占位符用于应用程序直接控制范围之外的查询部分。
如果已知映射键允许使用字段名称,请使用以下命令:
var values []interface{} var where []string for k, v := range m { values = append(values, v) where = append(where, fmt.Sprintf("%s = ?", k)) } r, err := db.QueryRow("SELECT name FROM users WHERE " + strings.Join(where, " AND "), values...)