将XML转换为表变量

时间:2013-05-03 16:01:18

标签: sql-server tsql xml-parsing sql-server-2012

任何人都可以告诉我如何将以下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

我一直在网上查看一些教程,但他们都假设每个'技能'节点都有相同数量的子节点。

提前致谢。

2 个答案:

答案 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