我想将记录从xml插入两个不同的表中。例如
<Root> <A> <AValue>value</AValue> <Children> <B> <BValue>2</BValue> </B> </Children> </A> <A> <AValue>value</AValue> <Children> <B> <BValue>3</BValue> </B> </Children> </A> </Root>
将记录插入到表A中假设标识从1开始
AID AValue 1 value 2 value
还要在表B中插入一条记录
BID AID BValue 1 1 2 2 2 3
我有这个
DECLARE @idoc INT DECLARE @doc NVARCHAR(MAX) SET @doc = ' <Root> <A> <AValue>value</AValue> <Children> <B> <BValue>2</BValue> </B> </Children> </A> <A> <AValue>value</AValue> <Children> <B> <BValue>3</BValue> </B> </Children> </A> </Root> ' EXEC sp_xml_preparedocument @idoc OUTPUT, @doc CREATE TABLE #A ( AID INT IDENTITY(1, 1) , AValue varchar(100) ) INSERT INTO #A SELECT * FROM OPENXML (@idoc, '/Root/A',2) WITH (AValue varchar(100) ) CREATE TABLE #B ( BID INT IDENTITY(1, 1) , AID INT , BValue INT ) INSERT INTO #B SELECT * FROM OPENXML (@idoc, '/Root/A/Children/B',2) WITH ( AID INT, BValue INT ) SELECT * FROM #A SELECT * FROM #B DROP TABLE #A DROP TABLE #B exec sp_xml_removedocument @idoc
谢谢!
您需要保持相关性,下面将向您展示如何做。我还通过添加很多灵活性来使其更加健壮。
DECLARE @A table ( -- start with non-1, to show the solution is not dependent on starting at 1 AID INT IDENTITY(14, 1) , AValue varchar(100) ) DECLARE @B TABLE ( BID INT IDENTITY(1, 1) , AID INT , BValue INT ) DECLARE @xml XML -- allow for duplicate values on A.AValue -- allow for multiple B nodes -- allow for A nodes without B children SET @xml = ' <Root> <A> <AValue>value2</AValue> <Children> <B> <BValue>2</BValue> </B> <B> <BValue>4</BValue> </B> </Children> </A> <A> <AValue>value1</AValue> <Children> <B> <BValue>3</BValue> </B> </Children> </A> <A> <AValue>value1</AValue> <Children> <B> <BValue>9</BValue> </B> </Children> </A> <A> <AValue>valueX</AValue> </A> </Root> ' -- dump the data into a temp table for correlating A and B entries -- since an A can have multiple B children, ARow identifies which A it really is, -- multiple A records can have the same AValue declare @tmp table (ARow int, avalue varchar(100), bvalue int) INSERT @tmp (ARow, avalue, bvalue) SELECT X.N, X.C.value('A[1]/AValue[1]','varchar(100)'), Y.V FROM ( SELECT T.C.query('.') C, row_number() over (order by C) N FROM @xml.nodes('//A') T(C)) X OUTER APPLY ( SELECT T2.C2.value('.','int') V FROM X.C.nodes('A[1]/Children/B/BValue') T2(C2)) Y -- uncomment next line to see what has gone into @tmp -- select * from @tmp insert @A select AValue from ( select distinct ARow, AValue from @tmp) X order by ARow -- order by is important to maintain correlation -- get the last identity generated to correlate AID in B declare @lastid int SET @lastid = scope_identity() -- Max(ARow) is how many A records were entered, add back ARow to get -- the ID generated for the A record insert @B (AID, BValue) select @lastid-M.M+ARow, BValue from @tmp, (select max(ARow) M from @tmp) M where BValue is not null order by ARow -- check results select * from @A select * from @B