使用ISNULL的可选where子句

时间:2012-09-11 15:44:45

标签: sql-server-2005

我有存储过程采用多个参数(在某些情况下最多7或8)用于过滤结果集。这些参数是可选的(默认NULL)。传入的所有非NULL值都将在过滤器中使用(即它是布尔and而不是布尔or)。

这些查询通常看起来像这样......

SELECT *
FROM [MyTable]
WHERE (@Param1 IS NULL OR (@Param1 IS NOT NULL AND [Field1] = @Param1))
      AND (@Param2 IS NULL OR (@Param2 IS NOT NULL AND [Field2] = @Param2))
      AND (@Param3 ...

我知道这是非常低效的,但由于参数的数量,它们不可能将它们分成单独的查询。

所以我试着做以下......

SELECT *
FROM [MyTable]
WHERE [Field1] = ISNULL(@Param1, [Field1])
      AND [Field2] = ISNULL(@Param2, [Field2])
      AND [Field3] ...

但是,当字段包含NULL时会出现问题,因此=运算符根本不起作用。

是否有一种简单有效的方法可以使用多个“过滤器”参数进行单一查询?如果可能的话,我宁愿不使用动态SQL。

2 个答案:

答案 0 :(得分:1)

好吧,你可以简化你的初始SQL,因为你已经在每个子句中测试了NULL

SELECT *
FROM [MyTable]
WHERE (@Param1 IS NULL OR [Field1] = @Param1)
      AND (@Param2 IS NULL OR [Field2] = @Param2)
      AND (@Param3 ...

这不一定是效率低下的。如果您经常传入导致执行计划截然不同的参数组合,那么检查参数嗅探问题可能是明智的。

答案 1 :(得分:0)

使用“is null”的替代方法是进行此比较:

where coalesce(Field1, @Param1, '') = coalesce(@Param1, Field1, '') . . .

如果Field1或@Param1中的一个具有值,则两个COALESCE将返回该值。只有两者都是NULL,你才能进入第三个争论。

碰巧你可以将''转换为任何类型,因此也包括在内。但是,使用该函数往往会阻止索引的用户。