循环遍历存储过程中的数组

时间:2013-08-13 21:52:03

标签: c# tsql loops merge

场景:

我需要从存储过程返回一个结果集,但是我有一个数组参数可以传递未知的多个值,对于传递的每个值,我需要有一个单独的逻辑来获取数据。

SP:

PROCEDURE [dbo].[GetRecommendations]
(
  @RecommendationTypesCSV  varchar(4000) -- This could have Type1,Type2,Type3...
}

BEGIN
....
END 

一旦我转换了这个逗号分隔类型,我需要遍历每个类型并执行一些逻辑,但是当我继续执行所需的逻辑时,我收集数据,最后我必须做一个Union All并返回所有结果作为一个带有新类型的大结果集,并为其分配相关的类型信息。

If (type1)
BEGIN 
-- Do Something
END

If (type2)
BEGIN 
-- Do Something
END

If (type3)
BEGIN 
-- Do Something
END

合并所有三个并返回结果:

Column1     Column2     Column3
----------- ----------- -------
102570      10027       type1
102569      20011       type1
102568      20011       type1
102564      20011       type2
102563      20011       type2
102562      20074       type3
102561      20011       type3
102560      20011       type3
102559      10059       type3
102558      20011       type3

问题:

我需要决定是否应该单独调用DB(SQL)或每种类型的多个调用,然后将类型合并到代码(C#.Net)中,请记住这是面向服务和性能的WCF客户端是一个巨大的决策因素,而且类型不仅限于3种类型,而且可能是更多类型。

如果有效地进行单个数据库调用是光标唯一可能的循环类型并合并它们的方法 - 示例将不胜感激。

1 个答案:

答案 0 :(得分:1)

我们有一些使用这种技术的遗留系统。看起来有点像这样:

CREATE PROCEDURE [dbo].[GetRecommendations] 
    ( @RecommendationTypesCSV NVARCHAR(4000) ) 
AS  
BEGIN
   DECLARE @StartPos INT  
   DECLARE @EndPos INT  

   -- split recommendation types list into table  
   DECLARE @RecommendationTypes (  
       [Type] NVARCHAR(40)
   )  
   WHILE LEN(@RecommendationTypesCSV) > 0  
   BEGIN   
       SET @StartPos = 1  
       SET @EndPos = CHARINDEX(',', @RecommendationTypesCSV) - 1   
       IF @EndPos <= 0 SET @EndPos = LEN(@RecommendationTypesCSV)  

       INSERT INTO @RecommendationTypes VALUES (SUBSTRING(@RecommendationTypesCSV, @StartPos, @EndPos))  
       SET @RecommendationTypesCSV = SUBSTRING(@RecommendationTypesCSV, @EndPos + 2, LEN(@RecommendationTypesCSV))   
   END  

   If EXISTS (SELECT * FROM @RecommendationTypes WHERE [Type] = 'type1')
   BEGIN 
       -- Do Something
   END

   ...

END
GO

但通常我更喜欢尽可能使用table valued parameters

CREATE TYPE [dbo].[RecommendationTypes] AS TABLE 
    ( Type VARCHAR(40) );
GO
CREATE PROCEDURE [dbo].[GetRecommendations] 
    ( @RecommendationTypesCSV [dbo].[RecommendationTypes] READONLY ) 
AS  
BEGIN

   If EXISTS (SELECT * FROM @RecommendationTypes WHERE [Type] = 'type1')
   BEGIN 
       -- Do Something
   END

   ...

END
GO

唯一的问题是调用存储过程更加困难。

DECLARE @RecommendationTypesCSV [dbo].[RecommendationTypes];
INSERT @RecommendationTypesCSV VALUES ( 'type1' ), ( 'type2' );
EXEC [dbo].[GetRecommendations] @RecommendationTypesCSV