我有存储过程采用多个参数(在某些情况下最多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。
答案 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,你才能进入第三个争论。
碰巧你可以将''
转换为任何类型,因此也包括在内。但是,使用该函数往往会阻止索引的用户。