5

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

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

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

另一种方法是将其写为:

select * from TableA where ColumnB = @value

这可以由 C# 执行多次,但是这将导致 N DB 命中。

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

我正在使用 SQL 服务器和 OLDB,创建查询不是问题。我正在尝试创建最有效的流程。

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

4

3 回答 3

4

Assuming SQL Server 2008 or newer, in SQL Server, create a table type once:

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

Then a stored procedure that takes such a type as input:

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

Now in C#, create a DataTable and pass that as a parameter to the stored procedure:

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...;
}

(You might want to make the type a lot more generic, I named it specifically to make it clear what it is doing.)

于 2012-07-19T13:38:53.277 回答
2

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

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

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

于 2012-07-19T13:24:38.453 回答
0

你可以很容易地写这个:

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

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

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

于 2012-07-19T13:19:58.453 回答