如何将用户提供的输入添加到 SQL 语句中

本文关键字:添加 SQL 语句 输入 用户 | 更新日期: 2023-09-27 18:32:59

我正在尝试使用用户提供的数据创建一个SQL语句。我在 C# 中使用类似于下面的代码:

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

这在 VB.NET:

Dim sql = "INSERT INTO myTable (myField1, myField2) " &
          "VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()

然而

  • 当用户输入包含单引号(例如 O'Brien (,
  • 插入日期时间值时,我似乎无法获得正确的格式,并且
  • 人们一直告诉我,我不应该因为"SQL注入"而这样做。

我如何"以正确的方式"做到这一点?

如何将用户提供的输入添加到 SQL 语句中

使用参数化 SQL。

例子

(这些示例是 C# 中的,有关 VB.NET 版本,请参阅下文。

将字符串串联替换为@...占位符,然后将值添加到 SqlCommand。您可以自由选择占位符的名称,只需确保它们以@符号开头即可。您的示例如下所示:

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

相同的模式用于其他类型的 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是一个很好的起点,在大多数情况下工作正常。但是,传入的值需要与相应数据库字段的数据类型完全匹配。否则,最终可能会遇到转换阻止查询使用索引的情况。请注意,某些 SQL Server 数据类型,如 char/varchar(前面没有"n"(或日期没有相应的 .NET 数据类型。在这些情况下,应改用具有正确数据类型的Add

我为什么要这样做?

  • 更安全:它停止SQL注入。(Bobby Tables 不会删除您的学生记录。

  • 它更容易:无需摆弄单引号和双引号或查找日期文字的正确字符串表示形式。

  • 它更稳定:O'Brien不会仅仅因为他坚持保留他奇怪的名字而使你的应用程序崩溃。

其他数据库访问库

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

  • 实体框架还支持参数化查询。

VB.NET 示例代码

这是 vb.net 中 wiki 答案的示例代码,假设 Option Strict OnOption Infer On

插入

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

更新

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

选择

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