T-SQL does not support variadic parameters, and the IN
operator is not dynamically variadic, so if you do have this:
SELECT * FROM foo WHERE x IN ( @a, @b, @c, @d )
...and you have more than 4 possible values you'll need to manually add them to your SQL string, like so:
Object[] values = ...
SqlCommand cmd = connection.CreateCommand();
StringBuilder sb = new StringBuilder(" SELECT * FROM foo WHERE x IN (");
for( Int32 i = 0; i < values.Length; i++ ) {
if( i > 0 ) sb.Append(", ");
String name = " @param" + i.ToString( CultureInfo.InvariantCulture );
sb.Append( name );
cmd.Parameters.Add( name ).Value = values[i];
}
sb.Append( ")" );
cmd.CommandText = sb.ToString();
Obviously this doesn't work for complex queries.
Note that this approach is safe from SQL injection because we never put any values into the SQL string itself.
Another approach is a Table-Valued Parameter, which is much faster and scales to hundreds of thousands of values. SQL Server and SqlClient
supports it, but other database systems and client libraries don't.
- Define a table
TYPE
in your database for the values - even if they're an array of scalar values you still need to define the type.
- See instructions here on how to use Table-Value Parameters with
SqlCommand
: How to pass table value parameters to stored procedure from .net code
Perform a JOIN
on the table-values:
SELECT * FROM foo INNER JOIN @tableParam AS bar ON foo.x = bar.x
You can also use the IN
operator with a subquery (that uses the table-parameter), but performance is no better, or worse, compared to a JOIN
:
SELECT * FROM foo WHERE x IN ( SELECT x FROM @tableParam )