任何人都可以告诉我如何将以下XML字符串转换为具有以下结构的表变量:
DECLARE @xml XML = '<?xml version="1.0" encoding="UTF-8"?>
<skillsProfilesTargets>
<skill ID="1">
<profile ID="50" targetLevel="75" />
<profile ID="60" targetLevel="75.00"/>
<profile ID="70" targetLevel="60.00"/>
</skill>
<skill ID="2">
<profile ID="50" targetLevel="75" />
<profile ID="60" targetLevel="50.00"/>
</skill>
<skill ID="3">
<profile ID="50" targetLevel="" />
<profile ID="60" targetLevel="75"/>
<profile ID="90" targetLevel="60.00"/>
</skill>
<skill ID="4">
<profile ID="50" targetLevel="" />
<profile ID="60" targetLevel="75"/>
<profile ID="100" targetLevel="75"/>
<profile ID="250" targetLevel="100"/>
</skill>
</skillsProfilesTargets>'
SkillID profileID targetLevel
-----------------------------------
1 50 75
1 60 75
1 70 60
2 50 60
2 60 50
3 50 NULL
3 60 75
我一直在网上查看一些教程,但他们都假设每个'技能'节点都有相同数量的子节点。
提前致谢。
答案 0 :(得分:3)
这是另一种使用XQuery而不是sp_xml_preparedocument的解决方案(阅读每种方法的优缺点):
SELECT Skill.n.value('@ID', 'int') AS SkillID
, Profile.n.value('@ID','int') AS profileID
, Profile.n.value('@targetLevel','varchar(20)') AS targetLevel
FROM @xml.nodes('/skillsProfilesTargets/skill') AS Skill(n)
CROSS APPLY Skill.n.nodes('profile') AS Profile(n);
答案 1 :(得分:1)
我遇到的唯一问题是targetLevel在某些情况下有空格,这意味着我不能使用小数(10,2)。因此,targetLevel上的输出有空白而不是NULL。如果删除这些属性并将with子句中的targetLevel从varchar(10)更改为decimal(10,2),那么它将为您提供所需的输出。
以下是删除targetLevel的含义示例。
<skill ID="3">
<profile ID="50"/>
<profile ID="60" targetLevel="75"/>
<profile ID="90" targetLevel="60.00"/>
</skill>
下面是使用现有XML的答案。可能有办法强制空格显示为NULL,我只是不知道它。哦,当然你可以做SELECT * INTO @tablevar把数据放到表var。
DECLARE @xml XML = '<?xml version="1.0" encoding="UTF-8"?>
<skillsProfilesTargets>
<skill ID="1">
<profile ID="50" targetLevel="75" />
<profile ID="60" targetLevel="75.00"/>
<profile ID="70" targetLevel="60.00"/>
</skill>
<skill ID="2">
<profile ID="50" targetLevel="75" />
<profile ID="60" targetLevel="50.00"/>
</skill>
<skill ID="3">
<profile ID="50" targetLevel="" />
<profile ID="60" targetLevel="75"/>
<profile ID="90" targetLevel="60.00"/>
</skill>
<skill ID="4">
<profile ID="50" targetLevel="" />
<profile ID="60" targetLevel="75"/>
<profile ID="100" targetLevel="75"/>
<profile ID="250" targetLevel="100"/>
</skill>
</skillsProfilesTargets>'
declare @hxml int
EXEC sp_xml_preparedocument @hxml OUTPUT, @xml
SELECT *
FROM OPENXML(@hXML,'/skillsProfilesTargets/skill/profile',3)
WITH (SkillID INT '../@ID',
profileID INT '@ID',
targetLevel varchar(10))
EXEC sp_xml_removedocument @hxml