2017-10-21 45 views
2

Je n'ai jamais utilisé golang avec mysql auparavant, donc je suis en train de lire à propos de ça pour la première fois. Je voudrais faire quelque chose comme ceci:faire des requêtes dynamiques dans golang et 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) 

Ceci est beaucoup trop taper, surtout si j'ai une douzaine de plusieurs variables que je voudrais ajouter à la condition WHERE.

Si cela PHP, je ferais quelque chose comme ceci:

$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); 

En utilisant une boucle foreach, je peux générer dynamiquement des requêtes et de lier dynamiquement autant de variables selon les besoins.

Est-ce que quelque chose comme ceci est une option avec golang et mysql? Ou existe-t-il des alternatives à ne pas taper toutes les combinaisons de variables pour une requête?

Répondre

4

Si vous avez une carte avec les noms des champs et des valeurs comme celle-ci:

m := map[string]interface{}{"UserID": 1234, "Age": 18} 

alors vous pouvez construire la requête comme ceci:

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...) 

Ce n'est pas sensible à l'injection SQL parce que les espaces réservés sont utilisés pour des parties de la requête en dehors du contrôle direct de l'application.

Si les clés de carte sont connus pour être des noms de champs autorisés, utilisez ceci:

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...) 
+0

était sur le point critique sur l'injection SQL, mais cette solution ne limite en fait ce que la manipulation de la chaîne fait par ce qui est dans le code ... autant que je peux dire. – RayfenWindspear

+0

j'utilise aussi de cette façon! – Vutuz