2017-04-10 97 views
2

我有一個存儲過程,它選擇一些1-n關係和相關數據作爲XML數據引用列。SQL Server查詢性能:嵌套遊標

其目的是將一條記錄和1-n關係作爲一條記錄添加額外的數據列,這是通過將這些相關數據添加爲XML來完成的。

參考表:(表一)

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 
+0

好得多在這裏展示的樣本數據和預期的結果 –

+0

難道沒有返回預期的效果?如果你在這裏只是爲了找到有效的方法來做到這一點,那麼[代碼評論](http://codereview.stackexchange.com/)是這類類型問題的最佳選擇。 – mmushtaq

+0

是的,我試圖找到有效的方法。 我不知道代碼審查,謝謝 –

回答

1

一大堆可以凝結成幾行字,沒有遊標需要在所有。這西港島線在視圖中可用:

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 
+0

這是工作,因爲它應該。 這裏的問題是我必須從另一個表中獲取XML元素的名稱。 所以我認爲我必須使用動態查詢這是不可能的使用視圖 –

+1

@SepehrDavarnia請避免變色龍問題...在您的問題中,您提供樣本數據和預期的輸出。這兩個答案提供了一個(非常相似)的解決方案...現在你說,*這裏的問題是我必須從另一個表中獲取xml元素的名稱。* **我不知道你的意思是... ** SO的一個原則是:**一個問題,一個問題**。我會要求您對現有答案進行投票,選擇其中一個接受答案作爲解決方案,**開始一個新問題**,您將在這裏爲此新問題提供**更多信息**,樣本和預期輸出。 Thx – Shnugo

+0

嗨Shnugo。感謝您的建議。我以這種方式問了我的問題,因爲我認爲答案可能會解決問題。而且我還提供了我自己的查詢以顯示確切的事情。不管怎樣,謝謝你 –

1

有可能只用一個查詢來做到這一點 - 你可以使用子查詢與您的選擇如下:

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