1

谁能告诉我如何将以下 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

我一直在网上查看许多教程,但它们都假设每个“技能”节点都有相同数量的子节点。

提前致谢。

4

2 回答 2

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);
于 2013-05-03T16:30:43.313 回答
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
于 2013-05-03T16:26:04.440 回答