2012-08-07 59 views
2

是否可以将以下光标写入CTE?目前运行需要很长时间。将光标改为CTE

这里是我的代码:

if @ReportSource = 'TAB' 

    BEGIN 
    DECLARE yr_cursor CURSOR 
    FOR 
     SELECT YEAR, RouteNum, RampInfo, BeginMeasure, EndMeasure, OriginalRoute, Description, CountyDesc, Incidents from #RptParms 

    OPEN yr_cursor; 



FETCH NEXT FROM yr_cursor INTO @Year, @RouteNum, @RampInfo, @BeginMeasure, @EndMeasure, @OriginalRoute, @Description, @CountyDesc, @Incidents; 


WHILE (@@FETCH_STATUS = 0) 

    BEGIN 

     SELECT @sql_str_fred = N'SELECT route_number, beg_measure AS MILELOG, AADT_TOTAL AS VMT, end_measure, RCLINK,YEAR 
           FROM VW_FRED_AADT_HIST 
           WHERE route_number = '''+ @RouteNum + ''' 
           and YEAR = '''+ @Year + ''' 
           and FIPS_AND_COUNTY Like ' + '''%' + @CountyDesc + ''' 
           and beg_measure BETWEEN '+ cast(@BeginMeasure as varchar(8)) + ' and ' + cast(@EndMeasure as varchar(8)) + '' 




     SELECT @sql_str_fred = N' SELECT * from OPENQUERY(EDWGEARS, ''' + REPLACE(@sql_str_fred, '''', '''''') + ''')' 


         INSERT #freddata (ROUTE_NBR , 
             MILELOG , 
             VMT , 
             END_MEASURE , 
             RCLINK , 
             YEAR)   
         EXEC sp_ExecuteSQL @sql_str_fred 




       FETCH NEXT FROM yr_cursor INTO @Year, @RouteNum, @RampInfo, @BeginMeasure, @EndMeasure, @OriginalRoute, @Description, @CountyDesc, @Incidents; 

      END 

    CLOSE yr_cursor 
    DEALLOCATE yr_cursor 

END; 
+4

事实上,你正在做一个链接服务器的SP在每次迭代执行表明,这是不会用CTE的原样工作;也许有一种方法可以在一次打击中将所有相关数据传递给链接服务器,否则我会猜测你将不得不循环。 – AakashM 2012-08-07 15:42:49

+0

哪位? CTE应该比光标快的原因没有什么原因。 – 2012-08-07 15:44:34

+0

通过循环需要多少时间?你有多少个循环(平均)?您能否首先将远程数据的一个子集复制到本地临时表中? – milivojeviCH 2012-12-28 08:48:12

回答

0

假设#RptParms - 是pameter值的表,而不是巨大的... 然后,所有参数可与查询相结合这样的:

-- The maximum length of the query string in OPENQUERY is 8 KB !!! 
declare 
    @sql varchar(max) = ' 
;WITH lst AS (
    SELECT * FROM (VALUES 
--- values --- 
    ) aa(rn,yr,dsc,m1,m2) 
) SELECT route_number, beg_measure AS MILELOG, AADT_TOTAL AS VMT, end_measure, RCLINK,YEAR 
FROM VW_FRED_AADT_HIST lst 
WHERE route_number = lst.rn 
    and YEAR = lst.yr 
    and FIPS_AND_COUNTY Like lst.dsc 
    and beg_measure BETWEEN lst.m1 and lst.m2 
' 

    select @sql = REPLACE(@sql, '--- values ---', '--- values ---, 
(' + ISNULL('''' + RouteNum       + '''', 'NULL')  -- rn:  1234 --> '1234' or --> NULL 
+ ',' + ISNULL('''' + YEAR        + '''', 'NULL')  -- yn:  1234 --> '1234' 
+ ',' + ISNULL('''%' 
     + replace(replace(replace(replace(Description 
      , '[', '[[]') 
      , '%', '[%]') 
      , '_', '[_]') 
      , '''', '''''') 
     + '''', 'NULL')              -- dsc: a_b[c]%d'e --> '%a[_]b[[]c][%]d''e' 
+ ',' + ISNULL('''' + cast(BeginMeasure as varchar(8)) + '''', 'NULL')  -- m1:  1234 --> '1234' 
+ ',' + ISNULL('''' + cast(EndMeasure as varchar(8)) + '''', 'NULL')  -- m2:  1234 --> '1234' 
+ ')') 
    from #RptParms 

-- print @sql 
/* 
;WITH lst AS (
    SELECT * FROM (VALUES 

--- values ---, 
('1234','1234','%a[_]b[[]c][%]d''e','1234','1234'), 
('222',NULL,'%abcde','1234','1234'), 
(NULL,'1234','%a[_]b[[]c][%]d''e','1234','1234') 

    ) aa(rn,yr,dsc,m1,m2) 
) SELECT route_number, beg_measure AS MILELOG, AADT_TOTAL AS VMT, end_measure, RCLINK,YEAR 
FROM VW_FRED_AADT_HIST, lst 
WHERE route_number = lst.rn 
    and YEAR = lst.yr 
    and FIPS_AND_COUNTY Like lst.dsc 
    and beg_measure BETWEEN lst.m1 and lst.m2 
*/ 

INSERT #freddata (ROUTE_NBR, MILELOG, VMT, END_MEASURE, RCLINK, YEAR) 
    SELECT * 
    from OPENQUERY(EDWGEARS, @sql) 

再一次: OPENQUERY中查询字符串的最大长度是8 KB !!!