2

我有一张带有这些列的汽车表:

ID
BrandID
ModelID
ColorID
ProductionYear
Price
IsSecondHand
.
.
.

品牌、型号、颜色和...有自己的表格。

用户有广泛的过滤选项,也就是说所有过滤器都是可选的,用户可以选择也可以不选择品牌、型号、颜色等,可以选择生产年份范围、价格范围。甚至有些过滤器有多个值,例如用户可能会选择查看红色或白色的汽车。或者可以选择过滤多个模型。

我想编写一个存储过程来返回结果,并且我想找到一种方法来编写更简单且性能良好的代码。我不想在我的过程中使用 1000 个 if 子句。

有任何想法吗?

4

2 回答 2

3

如果查询可以依赖于许多不同的列,那么就没有好的单条 T-SQL 语句来处理它。要获得像体面的执行计划这样的东西,您需要针对您想要的确切组合的 T-SQL。执行此操作的方法是动态构建 SQL。

现在您有 3 个选项:

  • 在存储过程中生成 T-SQL,并用于sp_ExecuteSQL执行它(保留正确的参数化和查询计划重用)
  • 首先不要使用存储过程:在 C# 中生成 T-SQL 并执行它
  • 使用 ORM

第一个选项是可行的,但很痛苦——T-SQL 根本不适合这个。但你可以做到。例如(缩写):

declare @tsql nvarchar(4000) = 'select * from foo ...'
if @name is not null
    set @tsql = @sql + ' and Name = @name'
if @region is not null
    set @tsql = @sql + ' and Region = @region'
-- ...
exec sp_executesql @tsql,
        N'@name nvarchar(50), @region int`,
        @name, @region

C# 选项更容易 IMO - 通常通过StringBuilder- 只需添加您需要的子句和参数。

最后,使用 ORM(在本例中为 LINQ 提供程序):

IQueryable<Foo> foos = ctx.Foos;
if(name != null) foos = foos.Where(x => x.Name == name);
if(region != null) foos = foos.Where(x => x.Region == region);
// ...
于 2013-09-18T09:55:02.577 回答
2

尝试创建如下存储过程

    @BrandID INT,
    @ModelID INT
AS
    SELECT columns...
    FROM TABLE TB
    WHERE (@BrandID = 0 OR (TB.BrandID = @BrandID ))
      AND (@ModelID = 0 OR (TB.ModelID = @ModelID ))

您可以从后面的代码生成 SQL。所以你可以只放必要的条件

更新

如果用户可以为一个参数选择多个值,我建议您使用参数化 SQL IN 子句表值参数

于 2013-09-18T09:51:09.120 回答