2016-11-02 2 views
-1

I는, 예를 들면 (a C# 1 엔티티 그래프에서 생성) 복잡한 중첩 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 오타가 수정되었습니다. –

답변

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>'; 

--This 쿼리는 모든 데이터와 테이블 #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 

일단 테이블에 모든 데이터가 있으면 적절한 삽입을 위해 각 세트를 따로 따로 선택하기 위해 , GROUP BY, 필요한 경우 ROW_NUMBER() OVER(PARTITION BY ...)을 사용할 수 있습니다.

+0

중첩 된 값을 한 테이블의 열에 배치하여 작동합니다. 중첩 된 노드를 별도의 테이블로 추출 할 수 있습니까? 그리고 SELECT 부분에 무의식적 인 열을 전달하는 것을 피할 수 있습니까? –

+0

INSERT INTO YourCustomerTable (Id, Number) SELECT DISTINCT CustomerId, CustomerAccountNumber FROM #tmpInsert;를 사용하고 다른 모든 중첩 세트와 비슷합니다. '# tmpInsert'를 소스 테이블로 사용할 수 있습니다. 그리고 아니오 : 나는 개별 열을 그냥 버리는 것을 피할 것입니다. * 테이블이 어떤 시점에서든 간단히 변경 될 수 있습니다. 'INSERT INTO MyCustomerTabLE SELECT * FROM SomeWhere' - 물론입니다! - 앞으로 문제가 생길 것입니다! – Shnugo