我需要创建一个存储过程,该过程需要12个参数,并使用此参数的不同组合过滤查询。所有12个参数都不是强制性的,因为我传递3或5或12个参数取决于用户输入的搜索输入。
我可以创建两种方法,使用动态SQL查询或使用“Case where”语句。这些查询的示例如下:
动态查询
DECLARE @sql VARCHAR(MAX)
DECLARE @condition VARCHAR(MAX)=''
Declare @var1 varchar(10)
Declare @var2 varchar(10)
Declare @var3 varchar(10)
SET @sql='SELECT * FROM TableDemo1 TD1 WITH(NOLOCK)
INNER JOIN TableDemo2 TD2 ON TD1.Column1=TD2.Column2'
if(@var1 <>0 and @var1 is not null)
begin
if(@condition<>'')
begin
set @condition=@condition + ' and TD1.columnTest1='+@var1)
end
else
begin
set @condition=' where TD1.columnTest1='+@var1
end
end
if(@var2 <>0 and @var2 is not null)
begin
if(@condition<>'')
begin
set @condition=@condition + ' and TD2.columnTest2='+@var2)
end
else
begin
set @condition=' where TD2.columnTest2='+@var2
end
end
if(@var3 <>0 and @var3 is not null)
begin
if(@condition<>'')
begin
set @condition=@condition + ' and TD1.columnTest3='+@var3)
end
else
begin
set @condition=' where TD1.columnTest3='+@var3
end
end
SET @sql=@sql+@condition
EXEC(@sql)
使用CASE WHERE查询
Declare @var1 varchar(10)
Declare @var2 varchar(10)
Declare @var3 varchar(10)
SELECT *
FROM TableDemo1 TD1 WITH(NOLOCK)
INNER JOIN TableDemo2 TD2 ON TD1.Column1=TD2.Column2
WHERE
(CASE WHEN
(@var1<>0 and @var1 is not null)
THEN
CASE WHEN TD1.columnTest1=@var1 THEN 1 ELSE 0 END
ELSE 1 END)=1
AND
(CASE WHEN
(@var2<>0 and @var2 is not null)
THEN
CASE WHEN TD2.columnTest2=@var2 THEN 1 ELSE 0 END
ELSE 1 END)=1
AND
(CASE WHEN
(@var3<>0 AND @var3 IS NOT NULL)
THEN
CASE WHEN TD1.columnTest3 = @var3
THEN 1 ELSE 0 END
ELSE 1 END) =1
这只是我的存储过程的一部分,有7-8个表连接,并且如上所述在查询中有各种条件。
如果我使用动态查询,SQL Server每次都必须创建一个执行计划,但如果我使用'case where',它也会使查询变慢。
我知道动态SQL的缺点,但我应该使用哪种技术?
答案 0 :(得分:3)
根据我的经验,动态where
子句提供了更好的性能。特别是在大型数据集上。
在Catch All Queries中有一个非常好的解释。
答案 1 :(得分:3)
动态查询将导致索引扫描。
案例将导致seq扫描(即读取整个表格)。
所以一定要使用动态查询。
答案 2 :(得分:2)
通常它取决于,但大多数情况下我使用动态查询作为最后的手段。关于你的问题,我很可能会使用CASE解决方案,但我认为你的CASE表达式不必要地复杂化。我会用这样的东西替换WHERE子句:
...
WHERE
TD1.columnTest1 = COALESCE(NULLIF(@var1, 0), TD1.columnTest1)
AND
TD2.columnTest2 = COALESCE(NULLIF(@var2, 0), TD2.columnTest2)
AND
TD1.columnTest3 = COALESCE(NULLIF(@var3, 0), TD1.columnTest3)
通过适当的索引,这不应该太慢。
答案 3 :(得分:0)
我使用了使用coalesce和nullif函数发布的“Andriy M”选项。
但是此选项仅适用于'='运算符,但要找到如何将其与其他条件一起使用,一个示例是使用'IN'关键字。
TD1.columnTest1 = (
CASE
WHEN (
( TD1.columnTest1
IN (
SELECT item FROM dbo.Splitfunction(@comaSepValues,',')
)
)
OR
NULLIF(@PlaceTypeCode,'') IS NULL
) THEN columnTest1
ELSE NULL
END
)
让我知道这是否有效。
答案 4 :(得分:0)
执行动态查询有两种方法 1.执行 2. sp_executeSQL
如果要重用执行计划,请转到sp_executeSQL选项。
&#39; sp_executesql的&#39;接受参数,因此您可以直接将参数传递给此查询,该查询将实际重用您的执行计划。
动态查询的性能并不总是特别适合您正确使用