web-dev-qa-db-fra.com

Comment puis-je ajouter une entrée fournie par l'utilisateur à une instruction SQL?

J'essaie de créer une instruction SQL à l'aide de données fournies par l'utilisateur. J'utilise un code similaire à celui-ci en C #:

var sql = "INSERT INTO myTable (myField1, myField2) " +
          "VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";

var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();

et cela dans VB.NET:

Dim sql = "INSERT INTO myTable (myField1, myField2) " &
          "VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"

Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()

Cependant,

  • cela échoue lorsque l'entrée utilisateur contient des guillemets simples (par exemple O'Brien),
  • Je n'arrive pas à obtenir le bon format lors de l'insertion des valeurs DateTime et
  • les gens me disent que je ne devrais pas faire ça à cause de "l'injection SQL".

Comment dois-je procéder "de la bonne façon"?

45
Heinzi

Utilisez SQL paramétré.

Exemples

(Ces exemples sont en C #, voir ci-dessous pour la version VB.NET.)

Remplacez vos concaténations de chaînes par @... espaces réservés et, ensuite, ajoutez les valeurs à votre SqlCommand. Vous pouvez choisir librement le nom des espaces réservés, assurez-vous simplement qu'ils commencent par le @ signe. Votre exemple ressemblerait à ceci:

var sql = "INSERT INTO myTable (myField1, myField2) " +
          "VALUES (@someValue, @someOtherValue);";

using (var cmd = new SqlCommand(sql, myDbConnection))
{
    cmd.Parameters.AddWithValue("@someValue", someVariable);
    cmd.Parameters.AddWithValue("@someOtherValue", someTextBox.Text);
    cmd.ExecuteNonQuery();
}

Le même modèle est utilisé pour d'autres types d'instructions SQL:

var sql = "UPDATE myTable SET myField1 = @newValue WHERE myField2 = @someValue;";

// see above, same as INSERT

ou

var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = @someValue;";

using (var cmd = new SqlCommand(sql, myDbConnection))
{
    cmd.Parameters.AddWithValue("@someValue", someVariable);
    using (var reader = cmd.ExecuteReader())
    {
        ...
    }
    // Alternatively: object result = cmd.ExecuteScalar();
    // if you are only interested in one value of one row.
}

Un mot d'avertissement: AddWithValue est un bon point de départ et fonctionne très bien dans la plupart des cas. Cependant, la valeur que vous transmettez doit correspondre exactement au type de données du champ de base de données correspondant. Sinon, vous pourriez vous retrouver dans une situation où la conversion empêche votre requête de en utilisant un index . Notez que certains types de données SQL Server, tels que char/varchar (sans précéder "n") ou date n'ont pas de type de données .NET correspondant. Dans ces cas, Add avec le type de données correct doit être utilisé à la place .

Pourquoi devrais-je faire cela?

Autres bibliothèques d'accès à la base de données

51
Heinzi

Exemple de code VB.NET

Ceci est l'exemple de code pour réponse wiki dans vb.net , en supposant que Option Strict On et Option Infer On.

[~ # ~] insérer [~ # ~]

Dim sql = "INSERT INTO myTable (myField1, myField2) " & 
          "VALUES (@someValue, @someOtherValue);"

Using cmd As New SqlCommand(sql, myDbConnection)
    cmd.Parameters.AddWithValue("@someValue", someVariable)
    cmd.Parameters.AddWithValue("@someOtherValue", someTextBox.Text)
    cmd.ExecuteNonQuery()
End Using

[~ # ~] mise à jour [~ # ~]

Dim sql = "UPDATE myTable SET myField1 = @newValue WHERE myField2 = @someValue;"

' see above, same as INSERT

[~ # ~] sélectionnez [~ # ~]

Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = @someValue;"

Using cmd As New SqlCommand(sql, myDbConnection)
    cmd.Parameters.AddWithValue("@someValue", someVariable)
    Using reader = cmd.ExecuteReader()
        ' ...
    End Using
    ' Alternatively: Dim result = cmd.ExecuteScalar()
    ' if you are only interested in one value of one row.
End Using
2
Igor