2016-11-02 5 views
-1

Iは、例えば、(C#のエンティティグラフから生成された)複合ネストされたXMLを有する:入れ子になったXMLを対応するテーブルに変換する方法は?

<Customers> 
    <Customer> 
    <Id>1</Id> 
    <Number>12345</Number> 
    <Addresses> 
     <Address> 
     <Id>100</Id> 
     <Street>my street </street> 
     <city>London</city> 
     </Address> 
     <Address> 
     <Id>101</Id> 
     <street>my street 2</street> 
     <city>Berlin</city> 
     </Address> 
    </Addresses> 
    <BankDetails> 
     <BankDetail> 
     <Id>222</Id> 
     <Iban>DE8439834934939434333</Iban> 
     </BankDetail> 
     <BankDetail> 
     <Id>228</Id> 
     <Iban>UK1237921391239123213</Iban> 
     </BankDetail> 
    </BankDetails> 
    <Orders> 
     <Order>   
     <OrderLine>   
     </OrderLine> 
     </Order> 
    </Orders> 
    </Customer> 
</Customers> 

実際のテーブルに上記XMLデータを保存する前に、私はそれを最初に処理する必要があります。このため、対応するテーブルタイプを作成しました。これらのテーブルタイプのそれぞれは、新しいデータ(まだプライマリキーが割り当てられていない)を処理しているときにユニークなキーを生成するように、追加のカラム(ROWGUIDとしてguid)を持っています。この列を使用して、異なるテーブルタイプ間の関係の整合性を保ちます。

上記のネストされたXMLを対応するテーブルに変換するSQL構文は何ですか?子レコードは生成された親GUIDを参照する必要がありますか?

+0

あなたのXMLが間違っています(間違った終了タグ '')、おそらく間違った場所にいくつかの '> '文字があります...(' * my street> * ') – Shnugo

+0

この質問はすでに:http://stackoverflow.com/questions/3989395/convert-xml-to-table-sql-server – Penman

+0

@Shnugo Typoが修正されました。 –

答えて

1

このようにそれを試してみてください。

DECLARE @xml XML= 
N'<Customers> 
    <Customer> 
    <Id>1</Id> 
    <AccountNumber>12345</AccountNumber> 
    <Addresses> 
     <Address> 
     <Id>100</Id> 
     <street>my street&gt;</street> 
     <city>London</city> 
     </Address> 
     <Address> 
     <Id>101</Id> 
     <street>my street&gt;</street> 
     <city>Berlin</city> 
     </Address> 
    </Addresses> 
    <BankDetails> 
     <BankDetail> 
     <Id>222</Id> 
     <Iban>DE8439834934939434333</Iban> 
     </BankDetail> 
     <BankDetail> 
     <Id>228</Id> 
     <Iban>UK1237921391239123213</Iban> 
     </BankDetail> 
    </BankDetails> 
    <Orders> 
     <Order> 
     <OrderLine /> 
     </Order> 
    </Orders> 
    </Customer> 
</Customers>'; 

- このクエリは、すべてのデータをテーブル#tmpInsertを作成します。あなたは、コンテンツ

SELECT * FROM #tmpInsert; 
を確認することができます--Here

SELECT cust.value('Id[1]','int') AS CustomerID 
     ,cust.value('AccountNumber[1]','int') AS CustomerAccountNumber 
     ,addr.value('Id[1]','int') AS AddressId 
     ,addr.value('street[1]','nvarchar(max)') AS AddressStreet 
     ,addr.value('city[1]','nvarchar(max)') AS AddressCity 
     ,bank.value('Id[1]','int') AS BankId 
     ,bank.value('Iban[1]','nvarchar(max)') AS BankIban 
     ,ord.value('OrderLine[1]','nvarchar(max)') AS OrderLine 
INTO #tmpInsert 
FROM @xml.nodes('/Customers/Customer') AS A(cust) 
OUTER APPLY cust.nodes('Addresses/Address') AS B(addr) 
OUTER APPLY cust.nodes('BankDetails/BankDetail') AS C(bank) 
OUTER APPLY cust.nodes('Orders/Order') AS D(ord); 

- クリーニングアップ

GO 
DROP TABLE #tmpInsert 

テーブルにすべてのデータが入ったら、必要に応じてDISTINCTGROUP BYROW_NUMBER() OVER(PARTITION BY ...)を使用して、適切な挿入のために各セットを個別に選択することができます。

+0

これは、ネストされた値を1つのテーブルの列に配置することによって機能します。ネストされたノードを別々のテーブルに抽出することは可能ですか?そして、SELECT部分​​に無意味な列を渡すことは避けられますか? –

+0

INSERT INTO YourCustomerTable(Id、Number)を使用してください。SELECT DISTINCT CustomerId、CustomerAccountNumber FROM #tmpInsert;および他のネストされたすべてのセットと同様です。 '#tmpInsert'をすべてのソーステーブルとして使用できます。そして、いいえ:私は実際に*個々の列を取り除くことを避けるでしょう*あなたのテーブルは任意のポイントで簡単なINSERT INTO MyCustomerTabLE SELECT * FROM SomeWhere'が変更された時点で - 確かに変更されます! - 将来的にトラブルにつながる! – Shnugo

関連する問題