2011-03-28 58 views
0

我有一个父子XML数据。我想使用open xml在SQL中插入数据。 客户节点将进入客户表。并且生成的相应密钥将作为外键关系进入订单表。这个怎么做?SQL Server - 用父子关系打开XML

<Customers ContactName="Joe" CompanyName="Company1"> 
    <Orders OrderDate="2000-08-25T00:00:00"/> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 
</Customers> 
<Customers ContactName="Steve" CompanyName="Company2"> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 

</Customers> 
+1

如果您正在使用SQL Server 2005+,它的时间移动到XML数据类型和XPath查询 – RichardTheKiwi 2011-03-28 19:19:42

回答

2

我认为标识列CustomerIDOrderID在你CustomersOrders表的主键,并且您有CustomerID为FK在Orders。我使用CustomerNameContactName来找到要在Orders.CustomerID中使用的CustomerID。如果来自XML的客户有机会已经在客户表中,则应使用where not exists子句从插入中排除这些行。

首先是使用@Richard在他的评论中建议的XML变量的版本。

declare @Customers table (CustomerID int identity, ContactName varchar(50), CompanyName varchar(50)) 
declare @Orders table (OrderID int identity, CustomerID int, OrderDate datetime) 

declare @xml as xml = ' 
<Customers ContactName="Joe" CompanyName="Company1"> 
    <Orders OrderDate="2000-08-25T00:00:00"/> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 
</Customers> 
<Customers ContactName="Steve" CompanyName="Company2"> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 
</Customers>' 

insert into @Customers (ContactName, CompanyName) 
select 
    c.value('@ContactName', 'varchar(50)'), 
    c.value('@CompanyName', 'varchar(50)') 
from @xml.nodes('Customers') as n(c) 

;with cteOrders as 
(
    select 
    o.value('@OrderDate', 'DateTime') as OrderDate, 
    o.value('../@ContactName', 'varchar(50)') as ContactName, 
    o.value('../@CompanyName', 'varchar(50)') as CompanyName 
    from @xml.nodes('Customers/Orders') as n(o) 
) 
insert into @Orders (CustomerID, OrderDate) 
select C.CustomerID, O.OrderDate 
from cteOrders as O 
    inner join @Customers as C 
    on C.CompanyName = O.CompanyName and 
     C.ContactName = O.ContactName 

第二个版本使用openxml。如果您使用openxml,则只能有一个根元素,因此我向示例XML添加了一个根元素。

declare @Customers table (CustomerID int identity, ContactName varchar(50), CompanyName varchar(50)) 
declare @Orders table (OrderID int identity, CustomerID int, OrderDate datetime) 

declare @xml as xml = ' 
<root> 
    <Customers ContactName="Joe" CompanyName="Company1"> 
    <Orders OrderDate="2000-08-25T00:00:00"/> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 
    </Customers> 
    <Customers ContactName="Steve" CompanyName="Company2"> 
    <Orders OrderDate="2000-10-03T00:00:00"/> 
    </Customers> 
</root>' 

declare @idoc int 
exec sp_xml_preparedocument @idoc out, @XML 


insert into @Customers (ContactName, CompanyName) 
select C.ContactName, C.CompanyName 
from openxml(@idoc, '/root/Customers', 0) with 
        (ContactName varchar(50), 
        CompanyName varchar(50)) as C 


insert into @Orders (CustomerID, OrderDate) 
select C.CustomerID, OrderDate 
from openxml(@idoc, '/root/Customers/Orders', 0) with 
      (OrderDate datetime, 
      ContactName varchar(50) '../@ContactName', 
      CompanyName varchar(50) '../@CompanyName') as O 
    inner join @Customers as C 
    on C.CompanyName = O.CompanyName and 
     C.ContactName = O.ContactName 

exec sp_xml_removedocument @idoc