我被FOR XML
困住了。我正在使用SQL Server 2008。
我正在尝试使用FOR XML
生成XML。
请参阅http://sqlfiddle.com/#!9/4e180e
我想将数据转换为以下XML
格式。我想将标签转换为标签<Headers>
,将数据转换为数据标签。在我的实际场景中,表中的列数是动态的。
我会请求你是否可以建议一种生成XML的动态方法,其中列数不应影响XML生成的逻辑。
<RootNode>
<Subject>
</SubjectID=94>
<FORMName>
<Headers>
<Header>VISIT</Header>
</Headers>
<Datas>
<Data>1<Data>
</Datas>
<Headers>
<Header>Date</Header>
</Headers>
<Datas>
<Data>8 Aug<Data>
</Datas>
<Headers>
<Header>Doc Name</Header><Header>Hostipal Name</Header>
</Headers>
<Datas>
<Data>Dr Sam</Data><Data>Happy Memorial</Data>
</Datas>
<Datas>
<Data>Dr Sam</Data><Data>Happy Memorial</Data>
</Datas>
</FORMName>
</Subject>
<RootNode>
我陷入了初始阶段,无法前进。
请帮帮我。
答案 0 :(得分:1)
这种结构是 - 嗯 - 很奇怪......
您的表格类似于Key-Value-Pair
,其中包含1:n-dependency
标题和数据。这违反了几个规范化规则......
您的XML只能通过标题及其数据的相应位置进行查询。试想一些数据为NULL
,你也必须处理这个......
顺便说一句:您的</SubjectID=94>
无效......
如果您是此结构的所有者,您应该考虑如何改进此结构?
然而,这可以做到 - 虽然我不会:
CREATE TABLE DataCols (
ID INT NOT NULL IDENTITY PRIMARY KEY,
SubjectID INT,
FormName VARCHAR(100),
ItemDetail VARCHAR(100),
POSITION INT,
col1 VARCHAR(255),
col2 VARCHAR(255)
);
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(94,'TOX','Label',0,'Visit');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(94,'TOX','Data',0,'1');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(94,'TOX','Label',0,'Date');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(94,'TOX','Date',0,'8 Aug');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Label',1,'Doc Name','Hostipal Name');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Data',1,'Dr Sam','Happy Memorial');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Data',2,'Dr Sam','Happy Memorial');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(98,'TOX','Label',0,'Visit');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(98,'TOX','Data',0,'1');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(98,'TOX','Label',0,'Date');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1) VALUES(98,'TOX','Date',0,'4 Jan');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Label',1,'Doc Name','Hostipal Name');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Data',1,'Dr Sam','Vegas Hostipal');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Data',2,'Dr Sam','Vegas Hostipal');
GO
- 这是查询:
WITH DistinctID AS
(SELECT DISTINCT SubjectID FROM DataCols)
,Labels AS
(
SELECT SubjectID
,ID
,(SELECT col1 AS Header,'',col2 AS Header FOR XML PATH('Headers'),TYPE) AS HeaderXML
FROM DataCols AS c
WHERE ItemDetail='Label'
)
,LabelsExt AS
(
SELECT *
,(SELECT MIN(x.ID) FROM Labels AS x WHERE x.ID>Labels.ID) AS NextID
FROM Labels
)
SELECT SubjectID
,(
SELECT HeaderXML AS [*]
,(SELECT col1 AS Data,'',col2 AS Data
FROM DataCols
WHERE DataCols.ID BETWEEN l.ID+1 AND ISNULL(l.NextID,999999)-1 FOR XML PATH('Datas'),TYPE) AS [*]
FROM LabelsExt AS l
WHERE l.SubjectID=DistinctID.SubjectID
FOR XML PATH(''),ROOT('FORMName'),TYPE
)
FROM DistinctID
FOR XML PATH('Subject'),ROOT('RootNode')
- 清理(如果有真实数据,请小心!)
GO
--DROP TABLE DataCols;
您可以尝试将此标题作为属性添加到数据元素中。一般来说,我更喜欢将元素命名为它们是什么......这样的结构只是在动态创建的字段的情况下,而不是事先知道结构。
WITH DistinctID AS
(SELECT DISTINCT SubjectID FROM DataCols)
,Labels AS
(
SELECT SubjectID
,ID
,col1,col2
FROM DataCols AS c
WHERE ItemDetail='Label'
)
,LabelsExt AS
(
SELECT *
,(SELECT MIN(x.ID) FROM Labels AS x WHERE x.ID>Labels.ID) AS NextID
FROM Labels
)
SELECT SubjectID
,(
SELECT (SELECT l.col1 AS [Data/@header], c.col1 AS Data
,''
,l.col2 AS [Data/@header], c.col2 AS Data
FROM DataCols AS c
WHERE c.ID BETWEEN l.ID+1 AND ISNULL(l.NextID,999999)-1
FOR XML PATH('Datas'),TYPE) AS [*]
FROM LabelsExt AS l
WHERE l.SubjectID=DistinctID.SubjectID
FOR XML PATH(''),ROOT('FORMName'),TYPE
)
FROM DistinctID
FOR XML PATH('Subject'),ROOT('RootNode')