1

xml を解析して挿入する例を見つけました。ただし、これらの例は非常に単純です。通常は次のようになります。

<person>
    <name>Martin</name>
</person>
<person>
    <name>John</name>
</person>

しかし、私はこれに似た XML を持っています - 子要素のために他のテーブルに挿入する必要がある場所。

<root>
    <family>
        <name>Smith</name>
        <address>Some road 1</address>
        <persons>
            <person>
                <name>Tina</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
            <person>
                <name>Martin</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
        </persons>
    </family>
    <family>
        <name>Lane</name>
        <address>Some road 1</address>
        <persons>
            <person>
                <name>Kevin</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
            <person>
                <name>Julia</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
        </persons>
    </family>
</root>

このxmlを反復処理し、最初に行をテーブル「Families」に挿入する必要があります。その後、家族のIDを返し、テーブル「Persons」内の人の次のINSERTで外部キーとして使用し、趣味と同じです. 私はあなたがアイデアを得ると思います。そして、「ファミリー」の後、次のファミリーに移る前にいくつかの更新ステートメントを実行する必要があります。

誰かが私を正しい方向に向けることができますか? 大歓迎です。

4

2 に答える 2

2

残念ながら、SQL Server は複数テーブルの挿入をサポートしていないため、次のように単一の挿入を行う必要があります。

insert into family  
    select f.node.value('name[1]', 'varchar(32)') as name
    from @xml.nodes('/root/family') f(node)

insert into person
    select family.ID as familyID, p.node.value('name[1]', 'varchar(32)') as name
    from @xml.nodes('/root/family') f(node)
    cross apply f.node.nodes('persons/person') p(node)
    inner join family on f.node.value('name[1]', 'varchar(32)') = family.name
于 2013-04-09T08:02:09.463 に答える
0

ここでの主な問題は、同じ名前のファミリを多数持つことができることです。私のソリューションは、この「側面」を考慮に入れています (注: テスト用に変更した XML を使用しました)。この例では、同じ名前 (Smith) であるが異なる 2 つのファミリを確認できます。人。これらのファミリには違いがあります。RowNum (および FamilyID)。トリッキーな部分は、姓の出現ごとにCROSS APPLYすべての要素を抽出する最後の部分です。/person

CROSS APPLY @x.nodes('/root/family[name=sql:column("f.Name")][sql:column("f.RowNum")]/persons/person') AS a(b)

注: このソリューションを開発して、すべての趣味を抽出することもできます。

DECLARE @x XML = N'
<root>
    <family>
        <name>Smith</name>
        <address>Some road 1</address>
        <persons>
            <person>
                <name>Tina</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
            <person>
                <name>Martin</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
        </persons>
    </family>
    <family>
        <name>Lane</name>
        <address>Some road 1</address>
        <persons>
            <person>
                <name>Kevin</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
            <person>
                <name>Julia</name>
                <hobbies>
                    <hobby>Some hobby 1</hobby>
                    <hobby>Some hobby 2</hobby>
                </hobbies>
            </person>
        </persons>
    </family>
    <family>
        <name>Smith</name>
        <address>Some another road 11</address>
        <persons>
            <person>
                <name>Coco</name>
            </person>
            <person>
                <name>Jambo</name>
            </person>
        </persons>
    </family>
</root>';

DECLARE @Family TABLE (
    FamilyID INT IDENTITY(1,1) UNIQUE,
    Name NVARCHAR(50) NOT NULL,
    RowNum INT NOT NULL,
    PRIMARY KEY (Name, RowNum)
);
INSERT  @Family (Name, RowNum)
SELECT  src.Name, 
        ROW_NUMBER() OVER(PARTITION BY src.Name ORDER BY @@SPID) AS RowNum
FROM (
    SELECT  a.b.value('(name)[1]', 'NVARCHAR(50)') AS Name
    FROM    @x.nodes('/root/family') AS a(b)
) src;

SELECT  f.*
FROM    @Family AS f

DECLARE @Person TABLE (
    PersonID INT IDENTITY(1,1) UNIQUE,
    FamilyID INT NOT NULL, -- Kind of FK
    Name NVARCHAR(50) NOT NULL,
    RowNum INT NOT NULL,
    PRIMARY KEY (Name, RowNum)  
)
INSERT  @Person (FamilyID, Name, RowNum)
SELECT  src.FamilyID, 
        src.Name,
        ROW_NUMBER() OVER(PARTITION BY src.FamilyID, src.Name ORDER BY @@SPID) AS RowNum
FROM (
    SELECT  f.FamilyID,
            a.b.value('(name)[1]', 'NVARCHAR(50)') AS Name
    FROM    @family f
    CROSS APPLY @x.nodes('/root/family[name=sql:column("f.Name")][sql:column("f.RowNum")]/persons/person') AS a(b)
) src;

SELECT  p.*
FROM    @Person AS p;

結果:

FamilyID Name  RowNum
-------- ----- ------
1        Lane  1
2        Smith 1
3        Smith 2

PersonID FamilyID Name   RowNum
-------- -------- ------ ------
5        3        Coco   1
6        3        Jambo  1
1        1        Julia  1
2        1        Kevin  1
3        2        Martin 1
4        2        Tina   1
于 2013-04-09T09:18:19.533 に答える