Comment puis-je ajouter une entrée fournie par l'utilisateur à une déclaration SQL?
j'essaie de créer une déclaration SQL en utilisant des données fournies par l'utilisateur. J'utilise le même code dans C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
et ceci en VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
Toutefois,
- ceci échoue lorsque l'entrée de l'utilisateur contient des guillemets simples (par exemple
O'Brien
), - Je ne semble pas pouvoir obtenir le bon format lors de l'insertion des valeurs DateTime et
- les gens n'arrêtent pas de me le dire que je ne devrais pas faire ça à cause de "SQL injection".
Comment faire "de la bonne façon"?
2 réponses
utiliser le SQL paramétrisé.
exemples
(ces exemples sont en C#, voir ci-dessous pour VB.NET version.)
Remplacez vos concaténations de chaînes de caractères par @...
placeholders et, ensuite, ajoutez les valeurs à votre SqlCommand. Vous pouvez choisir le nom des emplacements librement, assurez-vous juste 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 de déclarations 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 de mise en garde: AddWithValue
est un bon point de départ et fonctionne très bien dans la plupart des cas. Cependant, que la valeur que vous passez doit correspondre exactement au type de données du champ de base de données correspondant. Sinon, vous pourriez finir 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, comme 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 devrait être utilisé à la place .
Pourquoi devrais-je faire ça?
-
C'est plus sûr : ça s'arrête Injection SQL . ( Bobby Tables will not delete your student records. )
-
c'est plus facile: Pas besoin de tripoter avec des guillemets simples et doubles ou de chercher la représentation correcte de chaîne de caractères.
-
c'est plus stable:
O'Brien
ne va pas planter votre application juste parce qu'il insiste pour garder son nom étrange.
autres bibliothèques d'accès aux bases de données
-
si vous utilisez une commande OLEDB au lieu d'une commande SQL (par exemple, si vous utilisez une base de données MS Access), utilisez
?
au lieu de@...
comme paramètre dans le SQL. Dans ce cas, le premier paramètre deAddWithValue
n'est pas pertinent; vous devez plutôt ajouter les paramètres dans le bon ordre. le même est vrai pour OdbcCommand . -
Entity Framework prend également en charge les requêtes paramétrées.
VB.NET exemple de Code
Ceci est le code exemple pour le wiki answer dans vb.net , en supposant 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électionner
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