按参数列表筛选SQL查询

我有一个查询,我想返回与值列表关联的所有行。 你可以这么简单地写成:

select * from TableA where ColumnB in (1, 2, 3, 5) 

我可以用C#生成这个查询并执行它。 然而,这显然不太理想,因为它不使用参数,它会在尝试缓存查询计划时受到影响,并且显然容易受到SQL注入攻击。

另一种方法是将其写为:

 select * from TableA where ColumnB = @value 

这可以通过C#执行多次,但这会导致N DB命中。

我能看到的唯一另一个选择是创建一个临时表并以这种方式连接它,但是我没有看到这一点,因为它会更复杂并且受到与第一个选项相同的限制。

我正在使用SQL Server和OLDB,创建查询不是问题。 我正在努力创造最有效的流程。

这三种方法中哪一种更有效? 我错过了替代方案吗?

假设SQL Server 2008或更高版本,在SQL Server中创建一次表类型:

 CREATE TYPE dbo.ColumnBValues AS TABLE ( ColumnB INT ); 

然后是一个存储过程,它采用这样的类型作为输入:

 CREATE PROCEDURE dbo.whatever @ColumnBValues dbo.ColumnBValues READONLY AS BEGIN SET NOCOUNT ON; SELECT A.* FROM dbo.TableA AS A INNER JOIN @ColumnBValues AS c ON A.ColumnB = c.ColumnB; END GO 

现在在C#中,创建一个DataTable并将其作为参数传递给存储过程:

 DataTable cbv = new DataTable(); cbv.Columns.Add(new DataColumn("ColumnB")); // in a loop from a collection, presumably: cbv.Rows.Add(someThing.someValue); using (connectionObject) { SqlCommand cmd = new SqlCommand("dbo.whatever", connectionObject); cmd.CommandType = CommandType.StoredProcedure; SqlParameter cbvParam = cmd.Parameters.AddWithValue("@ColumnBValues", cbv); cbvParam.SqlDbType = SqlDbType.Structured; //cmd.Execute...; } 

(您可能希望使类型更通用,我专门命名它以明确它正在做什么。)

您还可以使用多个结果集并发送一个如下所示的查询:

 select * from TableA where ColumnB = @value0 select * from TableA where ColumnB = @value1 select * from TableA where ColumnB = @value2 ... select * from TableA where ColumnB = @valuen 

在一个电话中。 即使显然反直觉,它也会利用执行计划,并且在参数化方面是安全的。

你可以轻松写下这个:

 String csvString = "1, 2, 3, 5"; // Built the list somehow, don't forget escaping String query = "select * from TableA where ColumnB in (" + csvString + ")"; 

通过这种方式,性能不会降低,并且您可以在创建csvString阻止Sql Injection简单地转义输入值。

顺便说一句,如果您使用MS SQL而不是标准SQL,您可以找到 其他 方法 。