2010-06-16 54 views
0

我的工作是大量使用SQL服务器(MSSQL2005)的维护应用程序。
到目前为止,中间服务器将TSQL代码存储在XML中,并发送动态TSQL查询而不使用存储的特效代码。
由于我能够更改这些XML查询,我想将大部分查询迁移到存储的特效库。
问题是如下因素:Optimizing TSQL代码

我大部分的查询具有相同的若针对一个表的条件

样品:

Select 
    ..... 
from .... 
where .... 
and (a.vrsta_id = @vrsta_id or @vrsta_id = 0) 
and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0) 
and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0) 
and (
(a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina)) 
     group by art_id 
     having count(art_id)= @podosobina_count)) 
    or ('0' = @podosobina) 
) 

他们也有相同的地方上的其他表的条件。

我该如何组织我的代码?
什么是正确的方法?
我应该 使表的价值函数,我会用在所有查询
或使用#Temp表和简单的内部连接我的查询到每当proc执行? 或使用表值函数提交#temp?
或留下所有疑问,用这个大的where子句,并希望索引要完成他们的工作。
或使用WITH(语句)

回答

2

我已经认识到,在单个查询中进行如此复杂的搜索并不是一个好主意。

我更喜欢根据输入条件值构建sql。 这使得rsql服务器可以更轻松地为每个搜索构建更好的执行计划。 这种方式我敢打赌,你有一个次优执行计划为您的查询。

我意识到这将包括动态SQL,所以通常的警告适用于它。

2

这里有两个不同的功能问题:从一个表中选择值以及选择要返回的列或要连接到该数据的其他表。如果您在一张桌子上筛选的项目数量可能很大,我会倾向于将选定值的PK存储到中间或工作表中。如果它是一个永久性表格,您可以通过SessionId之类的东西来分隔不同的搜索,或者您可以将每组搜索结果与您从过滤例程传递给选择例程的随机值分开。

没有理由不能在动态SQL中保留过滤例程。但是,我不会尝试在T-SQL中执行动态SQL。 T-SQL对字符串操作很糟糕。从中间层动态构建查询使您能够从Where子句中排除实际不通过的元素。例如,当@vrsta_id实际上为零或者当@vrsta_id不为零时具有a.vrsta_id = @vrsta_id时,可以简单地排除这条线,而不是具有and (a.vrsta_id = @vrsta_id or @vrsta_id = 0)。通常,这种类型的查询将比一系列的OR更好。

一旦你有你的工作表,您的选择查询看起来是这样的:

Select.. 
From WorkTable As W 
    Join ... 

Where SetId = 12345 
    And (OtherTable.Col = .... 

在这种情况下,SetId将代表组从过滤程序创建的项目。

1

您可以创建一个表值函数,它接受参数并返回匹配a.id值的表。然后,您可以将该函数内联到每个存储过程的查询中。例如:

create function dbo.GetMatches 
(
@vrsta_id int, 
@podvrsta_id int, 
@podgrupa2_id int, 
@podosobina_count int 
) 
returns table 
as 
return 
Select 
a.id 
from a 
where 
(a.vrsta_id = @vrsta_id or @vrsta_id = 0) 
and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0) 
and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0) 
and (
(a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina)) 
group by art_id 
having count(art_id)= @podosobina_count)) 
or ('0' = @podosobina) 
) 
在这个例子中查询

则...

select 
* 
from 
a 
inner join dbo.GetMatches(1,2,3,4) matches 
on a.id = matches.id 
inner join b on a.bID = b.bID -- example other table 

您也可以使用该功能在where语句是这样的...

where 
    a.id in (select id from dbo.GetMatches(1,2,3,4))