如何将用户提供的input添加到SQL语句中?

我正在尝试使用用户提供的数据创build一个SQL语句。 我使用类似这样的代码:

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

然而,

  • 这在用户input包含单引号(例如O'Brien )时失败,
  • 插入date时间值和时,我似乎无法得到正确的格式
  • 人们不断告诉我,我不应该这样做,因为“SQL注入”。

我如何做到“正确的方式”?

使用参数化的SQL。

例子

@...占位符replacestring连接,然后将值添加到SqlCommand中。 您可以自由select占位符的名称,只要确保它们以@符号开头即可。 你的例子看起来像这样:

 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(); } 

其他types的SQL语句使用相同的模式:

 var sql = "UPDATE myTable SET myField1 = @newValue WHERE myField2 = @someValue;"; // see above, same as INSERT 

要么

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

谨慎的一句话: AddWithValue是一个很好的起点,在大多数情况下工作正常。 但是,您传递的值需要与相应的数据库字段的数据types完全匹配。 否则,在转换阻止您的查询使用索引的情况下,您可能会遇到这种情况。 请注意,某些SQL Server数据types(如char / varchar(不带前面的“n”)或date)没有相应的.NET数据types。 在这些情况下, 应该使用正确的数据typesAdd

我为什么要那么做?

  • 这是更安全的 :它停止SQL注入 。 ( 鲍比表不会删除你的学生logging。 )

  • 这很容易:不需要用单引号和双引号来查找,或查找date文字的正确string表示。

  • 这样更稳定: O'Brien不会因为坚持保持自己的名字而使应用程序崩溃。

其他数据库访问库

  • 如果您使用OleDbCommand而不是SqlCommand(例如,如果您正在使用MS Access数据库),请使用? 而不是@...作为SQL中的占位符。 在这种情况下, AddWithValue的第一个参数是不相关的; 相反,您需要以正确的顺序添加参数。 OdbcCommand也是如此 。

  • entity framework也支持参数化查询。