30

Inを使用してステートメントを実行する方法について混乱しているようですSqlParameter。これまでのところ、次のコードがあります。

cmd.CommandText = "Select dscr from system_settings where setting in @settings";
cmd.Connection = conn;
cmd.Parameters.Add(new SqlParameter("@settings", settingList));

reader = cmd.ExecuteReader();

settingsListですList<string>。がcmd.ExecuteReader()呼び出されると、 aを「既知のプロバイダー タイプ」ArgumentExceptionにマップできないために が発生します。List<string>

Ins を使用して (安全に)クエリを実行するにはどうすればよいSqlCommandですか?

4

6 に答える 6

33

次のようなことを試すことができます:

string sql = "SELECT dscr FROM system_settings WHERE setting IN ({0})";
string[] paramArray = settingList.Select((x, i) => "@settings" + i).ToArray();
cmd.CommandText = string.Format(sql, string.Join(",", paramArray));

for (int i = 0; i < settingList.Count; ++i)
{
    cmd.Parameters.Add(new SqlParameter("@settings" + i, settingList[i]));
}
于 2010-12-21T18:56:44.003 に答える
10

複数の値を持つパラメーターを渡そうとしているように見えますが、その SQL 構文は期待どおりに動作しません。テーブル値パラメーターを渡したい場合があります。

これを読んでください:http://www.sommarskog.se/arrays-in-sql.html#iter-list-of-strings

具体的には: http://www.sommarskog.se/arrays-in-sql-2008.html#ListSqlDataRecord

private static void datatable_example() {

   string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"};

   DataTable custid_list = new DataTable();
   custid_list.Columns.Add("custid", typeof(String));

   foreach (string custid in custids) {
      DataRow dr = custid_list.NewRow();
      dr["custid"] = custid;
      custid_list.Rows.Add(dr);
   }

   using(SqlConnection cn = setup_connection()) {
      using(SqlCommand cmd = cn.CreateCommand()) {

         cmd.CommandText =
           @"SELECT C.CustomerID, C.CompanyName
             FROM   Northwind.dbo.Customers C
             WHERE  C.CustomerID IN (SELECT id.custid FROM @custids id)";
         cmd.CommandType = CommandType.Text;

         cmd.Parameters.Add("@custids", SqlDbType.Structured);
         cmd.Parameters["@custids"].Direction = ParameterDirection.Input;
         cmd.Parameters["@custids"].TypeName = "custid_list_tbltype";
         cmd.Parameters["@custids"].Value = custid_list;

         using (SqlDataAdapter da = new SqlDataAdapter(cmd))
         using (DataSet        ds = new DataSet()) {
            da.Fill(ds);
            PrintDataSet(ds);
         }
      }
   }
}
于 2010-12-21T18:57:31.017 に答える
0

私はこれまでに独自の関数を使用して、次のようなパラメーターを作成しました。

public void SomeDataFunction() {    
    ArrayList params = GetParameters(someEntity);
    CommandObject.Parameters.AddRange(parameters.ToArray());
}

public static ArrayList GetParameters(ISomeEntity entity) {
    ArrayList result = new ArrayList {                  
            OleDbUtility.NewDbParam("@Param1", OleDbType.Integer, , entity.Parameter1),
            OleDbUtility.NewDbParam("@Param2", OleDbType.VarChar, 9, entity.Parameter2),
        }
}

public static OleDbParameter NewDbParam(string parameterName, OleDbType dataType,
                    int size, object value) {
    OleDbParameter result = new OleDbParameter(parameterName, dataType, size, string.Empty);
    result.Value = value;
    return result;
}
于 2010-12-21T19:03:09.713 に答える
0

Sql Server 2008 以降を使用している場合は、テーブル値パラメーターを使用できます。これにより、値のテーブルをパラメーターとして渡すことができます。.net から、「構造化された」タイプの SqlParameter を定義し、値を IEnumerable を実装するものに設定します。

ここで例を含む完全な MSDN リファレンスを参照してください: http://msdn.microsoft.com/en-us/library/bb675163.aspx

于 2010-12-21T19:04:01.530 に答える
-1

XML を使用すると、このシナリオでは十分に高速です。リストを XML に変換し、単純に文字列を渡します。

CREATE TABLE #myTempTable
(   Letter VARCHAR(20) )

INSERT INTO  #myTempTable (Letter) VALUES ('A'), ('B')

Declare @xml XML = '<a>A</a><a>B</a><a>C</a>'

Select * from #myTempTable 
Where Letter in 
(Select p.value('.', 'VARCHAR(40)') AS [Letter] from @xml.nodes('//a') as t(p)) 

DROP TABLE #myTempTable
于 2010-12-21T19:23:48.660 に答える
-3

通常、リストをコンマ区切りの文字列として渡し、テーブル値関数を使用して文字列をテーブルに「分割」し、それを使用して別のクエリで結合します。

DECLARE @Settings TABLE (Sid INT)   
INSERT INTO @Settings(Sid)
SELECT CAST(Items AS INT) FROM dbo.Split(@SettingsParameter, ',')

もちろん、SQL Server 2008 を使用している場合を除き、テーブル値パラメーターを使用します。

于 2010-12-21T19:06:02.710 に答える