web-dev-qa-db-ja.com

SQLステートメントにユーザー指定の入力を追加するにはどうすればよいですか?

ユーザー提供のデータを使用して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)、
  • DateTime値を挿入するときにフォーマットを正しく取得できないようで、
  • 「SQLインジェクション」のため、私はこれを行うべきではない、と人々は私に言い続けています。

「正しい方法」でそれを行うにはどうすればよいですか?

45
Heinzi

パラメータ化された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は出発点として最適で、ほとんどの場合問題なく機能します。ただし、渡す値は、対応するデータベースフィールドのデータ型と正確に一致する必要があります。そうしないと、変換によってクエリが インデックスを使用 できなくなる可能性があります。 char/varchar(「n」を前に付けない)や日付などの一部のSQL Serverデータ型には、対応する.NETデータ型がないことに注意してください。そのような場合は、正しいデータ型の Addを代わりに使用する必要があります

なぜそれをする必要があるのですか?

その他のデータベースアクセスライブラリ

51
Heinzi

VB.NETサンプルコード

これは、Option Strict OnOption Infer Onを想定した vb.netwiki answer のサンプルコードです。

[〜#〜]挿入[〜#〜]

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
2
Igor