2009-02-11 3 views
1

Я использую SQL Server 2005 и у меня есть столбец типа данных XML, который хранит фрагменты XML, как это в один большой стол:как создать XML из фрагментов XML

row 1 ..... <Order date='2009-02-11' customerID='4' /> 
row 2...... <OrderItem OrderID='6' ItemID='477' quantity='1' /> 

Я хотел бы создать XML с помощью T-SQL, который выглядит следующим образом:

<Orders> 
    <Order data='2009-02-11' customerID='4'> 
    <OrderItems> 
    <OrderItem OrderID='5' ItemID='477' quantity='1'/> 
    </OrderItems> 
    </Order> 
</Orders> 

Любые предложения? Спасибо.

ответ

0

Создайте UDF, который вызовет XmlDocument.LoadXml(). DocumentElement (root) - это любой другой XmlNodeList.

0

Самым большим препятствием с чистым решением T-SQL является конкатенация строк. Это небольшое T-SQL-решение, которое я взломал, должно делать трюк и работать быстро. Вероятно, было бы неплохо инкапсулировать это в UDF.

CREATE TABLE #Order (orderId INT PRIMARY KEY,[xmlData] NVARCHAR(512)) 
GO 
CREATE TABLE #OrderLines 
(orderId INT, orderLine INT,[xmlData] NVARCHAR(512),CONSTRAINT [pk_OrderLines] PRIMARY KEY CLUSTERED (orderId, orderLine)) 
GO 
INSERT INTO #Order 
SELECT 1, '<Order date="2009-02-11" customerID="4">' 

INSERT INTO #OrderLines 
SELECT 1, 1, '<OrderItem OrderID="1" ItemID="477" quantity="1" />' UNION ALL 
SELECT 1, 2, '<OrderItem OrderID="1" ItemID="478" quantity="1" />' 

-- 
-- Pivot Order lines into one string value 
-- 
DECLARE @OrderLines NVARCHAR(MAX) SET @OrderLines = '' 
SELECT @OrderLines = COALESCE(@OrderLines, ' ','') + [xmlData] from #OrderLines 
WHERE orderId = 1 


-- 
-- Join document fragments together into variable. 
-- 
DECLARE @XMLDOC NVARCHAR(MAX) SET @XMLDOC = '' 
SELECT @XMLDOC = COALESCE(@XMLDOC, ' ','') + a.C1 
FROM 
(
    SELECT '<Orders>' AS C1 UNION ALL 
    SELECT [xmlData] FROM #Order WHERE orderId = 1 UNION ALL 
    SELECT '<OrderItems>' UNION ALL 
    SELECT @OrderLines UNION ALL 
    SELECT '</OrderItems>' UNION ALL 
    SELECT '</Order>' UNION ALL 
    SELECT '</Orders>' 
) a 

SELECT @XMLDOC -- OUTPUT RESULT 
2

Это более прямолинейный метод с использованием XML DML в SQL Server 2005/2008, хотя есть немного kludginess к нему. Поскольку вы не можете вставить sql: переменную непосредственно в XML с помощью метода .modify (insert) типа данных XML, трюк заключается в том, что вам нужно отбросить фрагменты XML в виде символьных строк, объединить их, а затем переделать их как XML, переместите второй фрагмент внутри первого и удалите остатки второго. Реализация не так плохо, как это звучит:

DECLARE @xmlfrag1 XML 
DECLARE @xmlfrag2 XML 
DECLARE @xmlfrag3 XML 

SET @xmlfrag1 = '<Orders />' 
SET @xmlfrag2 = '<Order date="2009-02-11" customerID="4" />' 
SET @xmlfrag3 = '<OrderItem OrderID="5" ItemID="477" quantity="1"/>' 

SET @xmlfrag1 = CONVERT(XML, (CONVERT(NVARCHAR(MAX), @xmlfrag1) + CONVERT(NVARCHAR(MAX), @xmlfrag2))) 
SET @xmlfrag1.modify('insert /*[2] as first into /*[1]') 
SET @xmlfrag1.modify('delete /*[2]') 
SET @xmlfrag1.modify('insert <OrderItems /> as first into (/Orders/Order)[1]') 
SET @xmlfrag1 = CONVERT(XML, (CONVERT(NVARCHAR(MAX), @xmlfrag1) + CONVERT(NVARCHAR(MAX), @xmlfrag3))) 
SET @xmlfrag1.modify('insert /*[2] as first into (/Orders/Order/OrderItems)[1]') 
SET @xmlfrag1.modify('delete /*[2]') 

SELECT @xmlfrag1 

Это возвращает следующее, что это именно то, что вы хотели:

<Orders> 
    <Order date="2009-02-11" customerID="4"> 
    <OrderItems> 
     <OrderItem OrderID="5" ItemID="477" quantity="1" /> 
    </OrderItems> 
    </Order> 
</Orders> 

Как вы получаете ваши фрагменты XML полностью зависит от вас, но этого должно быть достаточно, чтобы вы начали.

0

- Временная таблица #t - это ваш стол. Поле OrderId необходимо, я полагаю, существует в вашей таблице.

 
create table #t (OrderId int, f xml) 
insert #t values (6,'') 
insert #t values (6,'') 


select 
1  as tag, 
null  as parent, 
t.OrderId   as [Order!1!!hide], 
f.value('(/Order/@date)[1]','varchar(10)') as [Order!1!data], 
f.value('(/Order/@customerID)[1]','int') as [Order!1!customerID], 
null   as [OrderItems!2!!hide], 
null   as [OrderItem!3!OrderID], 
null   as [OrderItem!3!ItemID], 
null   as [OrderItem!3!quantity] 
from #t as [t] 
where 
f.value('(/Order/@date)[1]','varchar(10)') is not null -- if is possible change the condition using another field 

union all 

select distinct 
2  as tag, 
1  as parent, 
t.OrderId   as [Order!1!!hide], 
null   as [Order!1!data], 
null   as [Order!1!customerID], 
1   as [OrderItems!2!!hide], 
null   as [OrderItem!3!OrderID], 
null   as [OrderItem!3!ItemID], 
null   as [OrderItem!3!quantity] 
from #t as [t] 

union all 

select 
3  as tag, 
2  as parent, 
t.OrderId   as [Order!1!!hide], 
null   as [Order!1!data], 
null   as [Order!1!customerID], 
1   as [OrderItems!2!!hide], 
f.value('(/OrderItem/@OrderID)[1]','int') as [OrderItem!3!OrderID], 
f.value('(/OrderItem/@ItemID)[1]','int') as [OrderItem!3!ItemID], 
f.value('(/OrderItem/@quantity)[1]','int') as [OrderItem!3!quantity] 
from #t as [t] 
where 
f.value('(/OrderItem/@OrderID)[1]','int') is not null-- if is possible change the condition using another field 


ORDER BY 
[Order!1!!hide], 
[OrderItems!2!!hide], 
[OrderItem!3!OrderID] 

FOR XML EXPLICIT, ROOT('Orders'), TYPE 
Смежные вопросы