SQL Server查询性能:嵌套游标

时间:2017-04-10 05:36:18

标签: sql sql-server cursor

我有一个存储过程,它将一些1-n关系和相关数据作为XML数据选择到引用列。

目的是将记录及其1-n关系作为ONE记录与额外数据列一起返回,这是通过将这些相关数据添加为XML来完成的。

参考表:(表A)

ID   NAME     VALUE
---------------------
1   Sepehr    1000    
2   Sarah     1001

相关表格:(表B)

ID   Value  FK_Value   ORDER    TITLE
-------------------------------------
1     A      1000         1      t1
2     B      1000         2      t2
3     C      1000         3      t3

我想得到这个输出:

ID   NAME    FK_Value   Attribs
-----------------------------------------------------
1   Sepehr    1000       <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2   Sarah     1001       null

实际上我希望创建一个视图来做到这一点,但我不能,有人告诉我它不可能使用视图。

最后这是我写的存储过程 - 这是一种正确的方法还是有其他方法吗?

DECLARE @T1 table (A_ID int,Attribs XML)   

DECLARE db_cursorLegendRowsValues CURSOR FOR 
    SELECT ID, VALUE 
    FROM A

OPEN db_cursorLegendRowsValues 

FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE

WHILE @@FETCH_STATUS = 0    
BEGIN   
    DECLARE db_cursorInternal CURSOR FOR 
        SELECT TITLE, ORDER 
        FROM B 
        WHERE FK_Value =  @loop_VALUE

    OPEN db_cursorInternal 

    FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @querySelect = @querySelect + ', MAX(CASE WHEN order = ' + cast(@ORDER as nvarchar(max)) + ' THEN value END) AS [' +REPLACE (@tmpTitle,' ','_') + '] '

        FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER
    END 

    CLOSE db_cursorInternal 
    DEALLOCATE db_cursorInternal

    SET @query = 
        ' SELECT ' +  cast(@loop_ID as nvarchar(max))  +',(
                            SELECT A.Value,  
        '
    SET @query = @query + STUFF(@querySelect,1,1,'') + ' FROM   A 
        WHERE [A.Value] = ' + cast(@loop_VALUE  as nvarchar(max)) + '
        FOR XML RAW (''Item''), root (''Items'') , ELEMENTS XSINIL )'

    SET @querySelect = ''
    --PRINT(@query) 

    INSERT into @T1  execute (@query )

    FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE
END

CLOSE db_cursorLegendRowsValues 
DEALLOCATE db_cursorLegendRowsValues

SELECT * FROM @T1

2 个答案:

答案 0 :(得分:1)

只需一个查询就可以执行此操作 - 您可以使用带有select的子查询,如下所示:

select id
    , name
    , value as fk_value
    , (select id from @table_b b
       where a.value = b.fk_value
       for xml path (''), root ('xml'))
from @table_a a

答案 1 :(得分:1)

整个批次可以缩写为几行,根本不需要游标。这将在VIEW中使用:

DECLARE @tblA TABLE(ID INT IDENTITY,NAME VARCHAR(100),VALUE INT);
INSERT INTO @tblA VALUES
 ('Sepehr',1000)    
,('Sarah',1001);

DECLARE @tblB TABLE(ID INT IDENTITY,Value VARCHAR(100),FK_Value INT,[ORDER] INT,TITLE VARCHAR(100));
INSERT INTO @tblB VALUES
 ('A',1000,1,'t1')
,('B',1000,2,'t2')
,('C',1000,3,'t3');

SELECT a.*
      ,(SELECT ID FROM @tblB AS b WHERE b.FK_Value=a.VALUE FOR XML PATH(''),ROOT('XML'),TYPE) AS Attribs
FROM @tblA AS a

结果

ID  NAME    VALUE   Attribs
1   Sepehr  1000    <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2   Sarah   1001    NULL