我在使用SQL生成XML方面有点新鲜。我试图从这个查询生成XML:
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 :(得分: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(而不是必须包含许多可能的节点名称的模式)。它将更自然地处理不同的分组可能性,它将处理FOR 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
请注意,你不应该这样做,这真的是丑陋的hackery (我只是告诉你如何在那里找到一部分的方式让你知道有多丑)。它真的变得更糟。我正在使用奇怪的字符串替换,可能会或可能不会在野外工作。最重要的是,如果任何节点有一个无效的XML字符,你必须逃避它 - 可能会抛出一些额外的替换(REPLACE(col, '<', '<')
)或其他东西,但这又是丑陋的,必须全部重复几个值。您基本上使用SQL Server作为XML编写器,它实际上并不意味着这样做。如果绝对必须具有此结构,那么您应该将数据传递给CLR类,该类可以正确使用XmlWriter
或XDocument
之类的内容来使用这些值编写实际的XML 。您甚至可以将CLR类放在SQL Server中并从存储过程中调用它。