2015-06-19 50 views
1

我在使用SQL生成XML方面有點新。我試圖從該查詢生成XML:作爲XML元素的SQL數據

SELECT RptType, DataType, Branch, ACC, Actual 
FROM ReportingTb 

查詢產生以下結果:

RptType DataType Branch Acc Actual 
------- -------- ------- ---- ----------- 
MTD  UPS  Arizona Total 2279.00000 
MTD  UPS  Arizona Oral 543.00000 
MTD  UPS  Arizona Tube 532.00000 
MTD  UPS  Arizona Other 1.00000 

我想使用的查詢結果中的前4列實際作爲這樣的XML元素:

<MTD> 
    <UPS> 
    <Arizona> 
     <Total> 
     <Actual>2279.00000</Actual> 
     </Total> 
     <Oral> 
     <Actual>543.00000</Actual> 
     </Oral> 
     <Tube> 
     <Actual>532.00000</Actual> 
     </Tube> 
     <Other> 
     <Actual>1.00000</Actual> 
     </Other> 
    </Arizona> 
    <UPS> 
</MTD> 

有人可以指出我在正確的方向如何做到這一點?我是否應該使用T-SQL並循環遍歷查詢的結果以創建XML文件?

感謝您的幫助!

+0

你不能這麼做 - 你不能使用像'9200'這樣的值在輸出XML中成爲XML標籤。您只能將SQL Server表中的值用作XML **屬性**或**元素**值 - 您不能使用這些值來創建XML結構。 –

+0

好的謝謝你的回答 – suexicano

+0

這不是關於*號碼* - 你只是**不能**使用**值**作爲XML標籤名稱! –

回答

0

這在技術上是可行的,但由於幾個原因,這確實很糟糕。相反,你應該重新考慮你的XML結構,以更多的東西是這樣的:

<Root> 
    <ReportingTb RptType="MTD" DataType="UPS" Branch="Arizona"> 
    <Actual Acc="Total">2279.00000</Actual> 
    <Actual Acc="Oral">543.00000</Actual> 
    <Actual Acc="Tube">532.00000</Actual> 
    <Actual Acc="Other">1.00000</Actual> 
    </ReportingTb> 
</Root> 

使用此查詢:

DECLARE @t TABLE (RptType varchar(20), DataType VARCHAR(20), Branch VARCHAR(20), Acc VARCHAR(20), Actual numeric(10,5)); 
INSERT @t VALUES 
('MTD', 'UPS'  ,'Arizona', 'Total', 2279.00000) 
,('MTD', 'UPS'  ,'Arizona', 'Oral', 543.00000) 
,('MTD', 'UPS'  ,'Arizona', 'Tube', 532.00000) 
,('MTD', 'UPS'  ,'Arizona', 'Other', 1.00000); 

SELECT RptType as '@RptType' 
    ,DataType as '@DataType' 
    ,Branch as '@Branch' 
    ,(SELECT 
     Acc AS '@Acc' 
     ,Actual as '*' 
    FROM @t t2 
    WHERE t2.RptType = t1.RptType AND t2.DataType = t1.DataType AND t2.Branch = t1.Branch 
    FOR XML PATH('Actual'), TYPE) 
FROM @t t1 
GROUP BY RptType, DataType, Branch 
FOR XML PATH('ReportingTb'), ROOT('Root'); 

這給你的XML,可以針對某個架構(而不是一個模式來合理驗證必須包含許多可能的節點名稱)。它會更自然地處理不同的分組可能性,並且會處理所有在後臺處理的XML怪異。

這就是說,在技術上可以達到你的原始願望;這裏有一個查詢,將做到這一點:

SELECT 
    CAST('<' + RptType + '>' 
    + (SELECT 
     '<' + DataType + '>' 
     + (SELECT 
      '<' + Branch + '>' 
      + REPLACE(REPLACE(
      (SELECT 
       '#' + acc + '!' as '*' , Actual, '#/' + acc + '!' as '*' 
       FROM @t t4 WHERE t4.Branch = t3.Branch AND t4.DataType = t2.DataType AND t4.RptType = t1.RptType 
       FOR XML PATH('')), '#', '<'), '!', '>') 

      + '</' + Branch + '>' 
      FROM @t t3 WHERE t3.DataType = t2.DataType AND t3.RptType = t1.RptType GROUP BY Branch) 
     + '</' + DataType + '>' 
     FROM @t t2 WHERE t2.RptType = t1.RptType GROUP BY DataType) 
    + '</' + RptType + '>' AS XML) 
FROM @t t1 
GROUP BY RptType 

注意,你不應該這樣做,這是十分可怕的兩輪牛車(我只顯示你給你的是如何醜陋,甚至獲得的部分想法那裏)。它真的只會變得更糟。我使用奇怪的字符串替換可能或不可能在野外工作。最重要的是,如果任何節點具有無效的XML字符,則必須將其轉義 - 可能需要進一步替換(REPLACE(col, '<', '&lt;'))或其他內容,但這又很醜陋,必須重複以上幾個值。你基本上使用SQL Server作爲一個XML編寫器,而這實際上並不意味着要這樣做。如果你絕對需要必須有這個結構,那麼你應該將數據傳遞給一個CLR類,它可以正確使用類似XmlWriterXDocument的東西來使用這些值編寫實際的XML。您甚至可以將CLR類放入SQL Server並從存儲過程調用它。