Подтвердить что ты не робот

Как я могу добавить вводимый пользователем ввод в инструкцию SQL?

Я пытаюсь создать инструкцию SQL, используя предоставленные пользователем данные. Я использую код, подобный этому в С#:

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),
  • Кажется, я не могу получить формат при вставке значений DateTime и
  • люди продолжают говорить мне, что я не должен этого делать из-за "инъекции SQL".

Как мне это сделать "правильно"?

4b9b3361

Ответ 1

Используйте параметризованный SQL.

Примеры

(Эти примеры приведены на С#, см. Ниже для версии 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: AddWithValue является хорошей отправной точкой и прекрасно работает в большинстве случаев. Однако, что значение, которое вы передаете, должно точно соответствовать типу данных соответствующего поля базы данных. В противном случае вы можете оказаться в ситуации, когда преобразование не позволяет вашему запросу использовать индекс. Обратите внимание, что некоторые типы данных SQL Server, такие как char/varchar (без предшествующих "n") или даты, не имеют соответствующего типа данных.NET. В таких случаях вместо этого следует использовать Add с правильным типом данных.

Почему я должен делать это?

  • Это более безопасно: он останавливает SQL-инъекцию. (Bobby Tables не удалит записи вашего студента).

  • Это проще: нет необходимости возиться с одиночными и двойными кавычками или искать правильное строковое представление литератур даты.

  • Это более стабильно: O'Brien не будет разбивать ваше приложение только потому, что он настаивает на сохранении своего странного имени.

Другие библиотеки доступа к базе данных

Ответ 2

Пример кода VB.NET

Это пример кода для ответа на wiki в , предполагая Option Strict On и Option 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