在SqlCommand中传递数组参数
我正在尝试传递数组参数到像下面的C#中的SQL commnd,但它不起作用。 有人见过吗?
string sqlCommand = "SELECT * from TableA WHERE Age IN (@Age)"; SqlConnection sqlCon = new SqlConnection(connectString); SqlCommand sqlComm = new SqlCommand(); sqlComm.Connection = sqlCon; sqlComm.CommandType = System.Data.CommandType.Text; sqlComm.CommandText = sqlCommand; sqlComm.CommandTimeout = 300; sqlComm.Parameters.Add("@Age", SqlDbType.NVarChar); StringBuilder sb = new StringBuilder(); foreach (ListItem item in ddlAge.Items) { if (item.Selected) { sb.Append(item.Text + ","); } } sqlComm.Parameters["@Age"].Value = sb.ToString().TrimEnd(',');
您将需要逐个添加数组中的值。
var parameters = new string[items.Length]; var cmd = new SqlCommand(); for (int i = 0; i < items.Length; i++) { parameters[i] = string.Format("@Age{0}", i); cmd.Parameters.AddWithValue(parameters[i], items[i]); } cmd.CommandText = string.Format("SELECT * from TableA WHERE Age IN ({0})", string.Join(", ", parameters)); cmd.Connection = new SqlConnection(connStr);
更新:这是一个扩展和可重用的解决scheme,使用亚当的答案与他的build议编辑。 我进行了一些改进,并将其作为一种扩展方法,使调用更加容易。
public static class SqlCommandExt { /// <summary> /// This will add an array of parameters to a SqlCommand. This is used for an IN statement. /// Use the returned value for the IN part of your SQL call. (ie SELECT * FROM table WHERE field IN ({paramNameRoot})) /// </summary> /// <param name="cmd">The SqlCommand object to add parameters to.</param> /// <param name="values">The array of strings that need to be added as parameters.</param> /// <param name="paramNameRoot">What the parameter should be named followed by a unique value for each value. This value surrounded by {} in the CommandText will be replaced.</param> /// <param name="start">The beginning number to append to the end of paramNameRoot for each value.</param> /// <param name="separator">The string that separates the parameter names in the sql command.</param> public static SqlParameter[] AddArrayParameters<T>(this SqlCommand cmd, IEnumerable<T> values, string paramNameRoot, int start = 1, string separator = ", ") { /* An array cannot be simply added as a parameter to a SqlCommand so we need to loop through things and add it manually. * Each item in the array will end up being it's own SqlParameter so the return value for this must be used as part of the * IN statement in the CommandText. */ var parameters = new List<SqlParameter>(); var parameterNames = new List<string>(); var paramNbr = start; foreach(var value in values) { var paramName = string.Format("@{0}{1}", paramNameRoot, paramNbr++); parameterNames.Add(paramName); parameters.Add(cmd.Parameters.AddWithValue(paramName, value)); } cmd.CommandText = cmd.CommandText.Replace("{" + paramNameRoot + "}", string.Join(separator, parameterNames)); return parameters.ToArray(); } }
这是这样的…
var cmd = new SqlCommand("SELECT * FROM TableA WHERE Age IN ({Age})"); cmd.AddArrayParameters(new int[] { 1, 2, 3 }, "Age");
请注意,sql语句中的“{Age}”与我们发送给AddArrayParameters的参数名称相同。 AddArrayParameters将用正确的参数replace该值。
我想扩大Brian的贡献,使之在其他地方很容易使用。
/// <summary> /// This will add an array of parameters to a SqlCommand. This is used for an IN statement. /// Use the returned value for the IN part of your SQL call. (ie SELECT * FROM table WHERE field IN (returnValue)) /// </summary> /// <param name="sqlCommand">The SqlCommand object to add parameters to.</param> /// <param name="array">The array of strings that need to be added as parameters.</param> /// <param name="paramName">What the parameter should be named.</param> protected string AddArrayParameters(SqlCommand sqlCommand, string[] array, string paramName) { /* An array cannot be simply added as a parameter to a SqlCommand so we need to loop through things and add it manually. * Each item in the array will end up being it's own SqlParameter so the return value for this must be used as part of the * IN statement in the CommandText. */ var parameters = new string[array.Length]; for (int i = 0; i < array.Length; i++) { parameters[i] = string.Format("@{0}{1}", paramName, i); sqlCommand.Parameters.AddWithValue(parameters[i], array[i]); } return string.Join(", ", parameters); }
你可以使用这个新的function如下:
SqlCommand cmd = new SqlCommand(); string ageParameters = AddArrayParameters(cmd, agesArray, "Age"); sql = string.Format("SELECT * FROM TableA WHERE Age IN ({0})", ageParameters); cmd.CommandText = sql;
编辑:这是一个通用的变化,与任何types的值的数组一起工作,可用作扩展方法:
public static class Extensions { public static void AddArrayParameters<T>(this SqlCommand cmd, string name, IEnumerable<T> values) { name = name.StartsWith("@") ? name : "@" + name; var names = string.Join(", ", values.Select((value, i) => { var paramName = name + i; cmd.Parameters.AddWithValue(paramName, value); return paramName; })); cmd.CommandText = cmd.CommandText.Replace(name, names); } }
然后你可以使用这个扩展方法如下:
var ageList = new List<int> { 1, 3, 5, 7, 9, 11 }; var cmd = new SqlCommand(); cmd.CommandText = "SELECT * FROM MyTable WHERE Age IN (@Age)"; cmd.AddArrayParameters("Age", ageList);
确保在调用AddArrayParameters之前设置CommandText。
还要确保您的参数名称不会与您的语句中的其他任何内容(即@AgeOfChild)
如果你可以使用像“dapper”这样的工具,这可以简单地:
int[] ages = { 20, 21, 22 }; // could be any common list-like type var rows = connection.Query<YourType>("SELECT * from TableA WHERE Age IN @ages", new { ages }).ToList();
小巧玲珑将把你的个人参数解开。
由于有一个方法
SqlCommand.Parameters.AddWithValue(parameterName, value)
创build一个接受参数(名称)replace的方法和一个值列表可能会更方便。 它不在参数级别(如AddWithValue )上,而是在命令本身上,所以最好将其称为AddParametersWithValues而不是AddWithValues :
查询:
SELECT * from TableA WHERE Age IN (@age)
用法:
sqlCommand.AddParametersWithValues("@age", 1, 2, 3);
扩展方法:
public static class SqlCommandExtensions { public static void AddParametersWithValues<T>(this SqlCommand cmd, string parameterName, params T[] values) { var parameterNames = new List<string>(); for(int i = 0; i < values.Count(); i++) { var paramName = @"@param" + i; cmd.Parameters.AddWithValue(paramName, values.ElementAt(i)); parameterNames.Add(paramName); } cmd.CommandText = cmd.CommandText.Replace(parameterName, string.Join(",", parameterNames)); } }
如果您使用的是MS SQL Server 2008及更高版本,则可以使用如http://www.sommarskog.se/arrays-in-sql-2008.html中所述的表值参数。;
1.为将要使用的每个参数types创build一个表types
以下命令为整数创build一个表types:
create type int32_id_list as table (id int not null primary key)
2.实施帮手方法
public static SqlCommand AddParameter<T>(this SqlCommand command, string name, IEnumerable<T> ids) { var parameter = command.CreateParameter(); parameter.ParameterName = name; parameter.TypeName = typeof(T).Name.ToLowerInvariant() + "_id_list"; parameter.SqlDbType = SqlDbType.Structured; parameter.Direction = ParameterDirection.Input; parameter.Value = CreateIdList(ids); command.Parameters.Add(parameter); return command; } private static DataTable CreateIdList<T>(IEnumerable<T> ids) { var table = new DataTable(); table.Columns.Add("id", typeof (T)); foreach (var id in ids) { table.Rows.Add(id); } return table; }
3.像这样使用它
cmd.CommandText = "select * from TableA where Age in (select id from @age)"; cmd.AddParameter("@age", new [] {1,2,3,4,5});
使用.AddWithValue()
,所以:
sqlComm.Parameters.AddWithValue("@Age", sb.ToString().TrimEnd(','));
另外,你可以使用这个:
sqlComm.Parameters.Add( new SqlParameter("@Age", sb.ToString().TrimEnd(',')) { SqlDbType = SqlDbType. NVarChar } );
你的总代码示例如下:
string sqlCommand = "SELECT * from TableA WHERE Age IN (@Age)"; SqlConnection sqlCon = new SqlConnection(connectString); SqlCommand sqlComm = new SqlCommand(); sqlComm.Connection = sqlCon; sqlComm.CommandType = System.Data.CommandType.Text; sqlComm.CommandText = sqlCommand; sqlComm.CommandTimeout = 300; StringBuilder sb = new StringBuilder(); foreach (ListItem item in ddlAge.Items) { if (item.Selected) { sb.Append(item.Text + ","); } } sqlComm.Parameters.AddWithValue("@Age", sb.ToString().TrimEnd(',')); // OR // sqlComm.Parameters.Add(new SqlParameter("@Age", sb.ToString().TrimEnd(',')) { SqlDbType = SqlDbType. NVarChar });
尝试
sqlComm.Parameters["@Age"].Value = sb.ToString().Replace(","," ");
或者你可以尝试一下简单的方法:
var ages = new int[] { 1, 2, 3, 4, 6 }; var selectSQL = "SELECT * from TableA WHERE Age IN ({0})"; var sql = String.Format(selectSQL , String.Join(",", ages)); using (var command = CreateCommand(connection, sql)) { command.CommandType = CommandType.Text; using (var reader = command.ExecuteReader()) { ... } }
只要在VB.NET中给出一个想法:
Dim yourVariable As String Dim item As Object For Each item In YourList.Items yourVariable = yourVariable + item + "," Next If yourVariable .EndsWith(",") Then yourVariable = yourVariable .Substring(0, Len(yourVariable ) - 1)
这就是全部!
现在把你的variables放入你的IN查询中
IN ( "& yourVariable &" )
或者变成参数化的:
IN (@yourVariableparametized)
像这样尝试
StringBuilder sb = new StringBuilder(); foreach (ListItem item in ddlAge.Items) { if (item.Selected) { string sqlCommand = "SELECT * from TableA WHERE Age IN (@Age)"; SqlConnection sqlCon = new SqlConnection(connectString); SqlCommand sqlComm = new SqlCommand(); sqlComm.Connection = sqlCon; sqlComm.CommandType = System.Data.CommandType.Text; sqlComm.CommandText = sqlCommand; sqlComm.CommandTimeout = 300; sqlComm.Parameters.Add("@Age", SqlDbType.NVarChar); sb.Append(item.Text + ","); sqlComm.Parameters["@Age"].Value = sb.ToString().TrimEnd(','); } }