2016-01-20 72 views
2

我有一個Xml文件,我試圖解析數據庫表。將xml傳遞到數據庫的SQL查詢

我有一些代碼可以做到這一點,但它不會將代碼合理地組織到表格中,因爲它會返回沒有任何順序的所有產品和房間。

正如您從下面看到的,xml首先定義了房間名稱和RoomId。

接下來是該房間將要出現的產品列表。 這些產品都存儲在一個表中,並已分配父母和孩子的ID。

XML然後爲不同的房間重複此結構。

我已經採取了一些代碼,因爲有很多的樣式和不必要的代碼。

我想要的是一個查詢,可以適當地存儲這些數據,以便我可以將它存儲在數據庫中,然後在SQL Server報表生成器中檢索它。

歡呼

XML

名稱空間

<t:RadDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:t="clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents" 

xmlns:s="clr-namespace:Telerik.Windows.Documents.Model.Styles;assembly=Telerik.Windows.Documents" 

xmlns:r="clr-namespace:Telerik.Windows.Documents.Model.Revisions;assembly=Telerik.Windows.Documents" 

xmlns:n="clr-namespace:Telerik.Windows.Documents.Model.Notes;assembly=Telerik.Windows.Documents" xmlns:th="clr-namespace:Telerik.Windows.Documents.Model.Themes;assembly=Telerik.Windows.Documents" 

xmlns:custom1="clr-namespace:TAS2;assembly=RadRichTextBoxExtensions" 

xmlns:custom2="clr-namespace:;assembly=RadRichTextBoxExtensions" version="1.2" LayoutMode="Paged" LineSpacing="1" LineSpacingType="Auto" ParagraphDefaultSpacingAfter="30" ParagraphDefaultSpacingBefore="30" SelectedBibliographicStyleName="\APA.XSL" StyleName="defaultDocumentStyle"> 

XML片斷

<custom1:RoomGroupRangeStart RoomID="26" RoomName="Bathroom" /> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Plumbing" ParentID="1"/> 
</custom1:SemanticRangeStart.Product> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Central Heating" ParentID="48" /> 
</custom1:SemanticRangeStart.Product> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Gas" ParentID="49" /> 
</custom1:SemanticRangeStart.Product> 

第一次嘗試

select 
    nodes.node.value('@ID', 'int') Id, 
    nodes.node.value('@Name', 'varchar(max)') Name, 
    nodes.node.value('@ParentID', 'int') ParentId 
from  
    @xml.nodes('//*:Products') nodes (node) 


select 
    nodes.node.value ('@RoomID', 'int') RoomID, 
    nodes.node.value ('@RoomName', 'varchar(max)') RoomName 
from  
    @xml.nodes('//*:RoomGroupRangeStart') nodes (node) 
+0

哪個RDBMS是爲了這個?請添加一個標籤來指定您是使用'mysql','postgresql','sql-server','oracle'還是'db2' - 或者其他的東西。 –

+0

道歉... SQL服務器 – Simula

+4

這不是一個有效的XML文檔 - 沒有單一的根元素。還有:顯然存在着XML命名空間(從'custom1:'前綴來看) - 但這些命令空間不可見 - 很可能是因爲XML文檔的某些部分丟失了...... –

回答

1

試試這樣說:

我添加了虛擬命名空間和幾個重複結構根節點...

DECLARE @x XML= 
'<t:RadDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:t="clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents" 
       xmlns:s="clr-namespace:Telerik.Windows.Documents.Model.Styles;assembly=Telerik.Windows.Documents" 
       xmlns:r="clr-namespace:Telerik.Windows.Documents.Model.Revisions;assembly=Telerik.Windows.Documents" 
       xmlns:n="clr-namespace:Telerik.Windows.Documents.Model.Notes;assembly=Telerik.Windows.Documents" xmlns:th="clr-namespace:Telerik.Windows.Documents.Model.Themes;assembly=Telerik.Windows.Documents" 
       xmlns:custom1="clr-namespace:TAS2;assembly=RadRichTextBoxExtensions" 
       xmlns:custom2="clr-namespace:;assembly=RadRichTextBoxExtensions" version="1.2" LayoutMode="Paged" LineSpacing="1" LineSpacingType="Auto" ParagraphDefaultSpacingAfter="30" ParagraphDefaultSpacingBefore="30" SelectedBibliographicStyleName="\APA.XSL" StyleName="defaultDocumentStyle"> 
    <custom1:RoomGroupRangeStart RoomID="26" RoomName="Bathroom" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Plumbing" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Central Heating" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Gas" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 

    <custom1:RoomGroupRangeStart RoomID="27" RoomName="Test" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Test1" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Test2" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Test3" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 

    <custom1:RoomGroupRangeStart RoomID="28" RoomName="OneMore" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="OneMore1" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="OneMore2" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="OneMore3" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 
</t:RadDocument>'; 
SELECT @x; 

您查詢像這樣

WITH XMLNAMESPACES('clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents' AS t 
        ,'clr-namespace:TAS2;assembly=RadRichTextBoxExtensions' AS custom1 
        ,DEFAULT 'http://schemas.microsoft.com/winfx/2006/xaml/presentation') 
,Numbered AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowInx 
      ,CASE WHEN The.Node.value('fn:local-name(.)','varchar(max)') = 'RoomGroupRangeStart' THEN 'Room' ELSE 'Product' END AS NodeType 
      ,CAST('<node>' + CAST(The.Node.query('.') AS VARCHAR(MAX)) + '</node>' AS XML) AS TheNode 
    FROM @x.nodes('/t:RadDocument/*') AS The(Node) 
) 
,DistinctRooms AS 
(
    SELECT Numbered.* 
      ,TheNode.value('(*//@RoomID)[1]','int') AS RoomID 
      ,TheNode.value('(*//@RoomName)[1]','varchar(max)') AS RoomName 
    FROM Numbered 
    WHERE NodeType='Room' 
) 

SELECT 
     dr.* 
     ,RelatedProducts.TheNode.value('(*//@HasChild)[1]','bit') AS HasChild 
     ,RelatedProducts.TheNode.value('(*//@ID)[1]','int') AS ProductID 
     ,RelatedProducts.TheNode.value('(*//@Level)[1]','int') AS Level 
     ,RelatedProducts.TheNode.value('(*//@Name)[1]','varchar(max)') AS ProductName 
     ,RelatedProducts.TheNode.value('(*//@ParentID)[1]','int') AS ParentID 

FROM DistinctRooms AS dr 
CROSS APPLY 
(
    SELECT products.* 
    FROM Numbered AS products 
    WHERE products.NodeType='Product' 
     AND products.RowInx BETWEEN dr.RowInx AND (SELECT ISNULL(MIN(x.RowInx),1000000) FROM DistinctRooms AS x WHERE x.RowInx>dr.RowInx) 
) AS RelatedProducts; 

結果

1 26 Bathroom 1 48 1 Plumbing   1 
1 26 Bathroom 1 49 2 Central Heating 48 
1 26 Bathroom 1 50 3 Gas    49 
5 27 Test  1 48 1 Test1   1 
5 27 Test  1 49 2 Test2   48 
5 27 Test  1 50 3 Test3   49 
9 28 OneMore  1 48 1 OneMore1   1 
9 28 OneMore  1 49 2 OneMore2  48 
9 28 OneMore  1 50 3 OneMore3  49 
+0

看起來不錯,但是我無法對xml進行任何更改。我將收到它作爲我想解析的文檔...對不起 – Simula

+0

@Simula沒有必要對XML進行更改。我剛剛創建了一個測試場景來讓這個運行... – Shnugo

+0

啊好的道歉...如果它們被編號會導致任何問題,如果每個文件稍有不同?即文件a上的空間可能比文件b上的更多產品? – Simula