sql >> データベース >  >> RDS >> Sqlserver

SQLIN句をパラメータ化する

    それぞれをパラメータ化できます 値なので、次のようになります:

    string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
    string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";
    
    string[] paramNames = tags.Select(
        (s, i) => "@tag" + i.ToString()
    ).ToArray();
    
    string inClause = string.Join(", ", paramNames);
    using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
        for(int i = 0; i < paramNames.Length; i++) {
           cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
        }
    }
    

    それはあなたに与えるでしょう:

    cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
    cmd.Parameters["@tag0"] = "ruby"
    cmd.Parameters["@tag1"] = "rails"
    cmd.Parameters["@tag2"] = "scruffy"
    cmd.Parameters["@tag3"] = "rubyonrails"
    

    いいえ、これはSQLインジェクションに対してオープンではありません。 CommandTextに挿入されるテキストは、ユーザー入力に基づくものだけではありません。これは、ハードコードされた「@tag」プレフィックスと配列のインデックスのみに基づいています。インデックスは常に 整数であり、ユーザー生成ではなく、安全です。

    ユーザーが入力した値はまだパラメータに詰め込まれているため、脆弱性はありません。

    編集:

    インジェクションの懸念はさておき、(上記のように)可変数のパラメーターに対応するようにコマンドテキストを作成すると、キャッシュされたクエリを利用するSQLサーバーの機能が妨げられることに注意してください。最終的な結果として、(述語文字列をSQL自体に挿入するだけではなく)そもそもパラメータを使用する価値がほぼ確実に失われます。

    キャッシュされたクエリプランは価値がないわけではありませんが、IMOのこのクエリは、それから多くのメリットを得るのに十分なほど複雑ではありません。コンパイルコストは実行コストに近づく(または超える)可能性がありますが、それでもミリ秒単位で話しています。

    十分なRAMがある場合は、SQLServerがパラメータの一般的なカウントの計画もキャッシュする可能性があります。いつでも5つのパラメーターを追加し、指定されていないタグをNULLにすることができると思います-クエリプランは同じである必要がありますが、それは私にはかなり醜いようで、マイクロ最適化の価値があるかどうかはわかりません(ただし、 StackOverflowで-それだけの価値があるかもしれません。

    また、SQL Server 7以降ではクエリが自動パラメータ化されるため、パフォーマンスの観点からパラメータを使用する必要はありませんが、重要 セキュリティの観点から-特にユーザーがこのようなデータを入力した場合。



    1. Oracle PL/SQLをPostgresqlPL/pgSQLに変換するためのツール

    2. 空の結果セットを返すJDBC

    3. MySQLのプロセスリストの表示に完全なSQLクエリを表示する

    4. EnterpriseEditionでNOEXPANDヒントを使用するもう1つの理由