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

sp_xml_preparedocument の代わりに XQuery を使用する別のソリューションを次に示します (各方法の長所と短所を読んでください)。

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 進数 (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 に答える