2

私は、自社製品のインストールに関する情報を含む大量の XML を格納するデータベースを持っています。XML 用に定義されたスキーマはなく、潜在的なすべてのタグのリストを持っている人もいません。

各レコードには、次のような数百の構造があります。

<array type="DWORD" name="m_somesetting.SMTPPorts" size="5"> 
   <set>19</set> 
   <set>1D0</set> 
   <set>14B</set> 
</array>

考えられる各タグの値と、何万件ものレコードのうちその特定の設定が含まれている数を示す表を作成するように依頼されました。

これを自動化する方法を知っている人はいますか? XML に対してクエリを実行する方法については十分に理解していますが、最初に存在する各タグを取得し、次に存在する一意の値をそれぞれ取得し、最後にその値を含むレコードの数を取得する方法が必要です。

考えられる各タグをクエリに手作業でコーディングする方法のアイデアはありますか?

4

2 に答える 2

0

xml からテーブルを作成する UDF

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[XMLTable](@x XML)  
RETURNS TABLE 
AS RETURN 
WITH cte AS (  
SELECT 
        1 AS lvl,  
        x.value('local-name(.)','NVARCHAR(MAX)') AS Name,  
        CAST(NULL AS NVARCHAR(MAX)) AS ParentName, 
        CAST(1 AS INT) AS ParentPosition, 
        CAST(N'Element' AS NVARCHAR(20)) AS NodeType,  
        x.value('local-name(.)','NVARCHAR(MAX)') AS FullPath,  
        x.value('local-name(.)','NVARCHAR(MAX)')  
        + N'[' 
        + CAST(ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS NVARCHAR)  
        + N']' AS XPath,  
        ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS Position, 
        x.value('local-name(.)','NVARCHAR(MAX)') AS Tree,  
        x.value('text()[1]','NVARCHAR(MAX)') AS Value,  
        x.query('.') AS this,         
        x.query('*') AS t,  
        CAST(CAST(1 AS VARBINARY(4)) AS VARBINARY(MAX)) AS Sort,  
        CAST(1 AS INT) AS ID  
FROM @x.nodes('/*') a(x)  
UNION ALL 
SELECT 
        p.lvl + 1 AS lvl,  
        c.value('local-name(.)','NVARCHAR(MAX)') AS Name,  
        CAST(p.Name AS NVARCHAR(MAX)) AS ParentName, 
    CAST(p.Position AS INT) AS ParentPosition, 
        CAST(N'Element' AS NVARCHAR(20)) AS NodeType,  
        CAST(p.FullPath + N'/' + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX)) AS FullPath,  
        CAST(p.XPath + N'/'+ c.value('local-name(.)','NVARCHAR(MAX)')+ N'['+ CAST(ROW_NUMBER() OVER(PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)') 
        ORDER BY (SELECT 1)) AS NVARCHAR)+ N']' AS NVARCHAR(MAX)) AS XPath,  
        ROW_NUMBER() OVER(PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)')
        ORDER BY (SELECT 1)) AS Position, 
        CAST( SPACE(2 * p.lvl - 1) + N'|' + REPLICATE(N'-', 1) + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX)) AS Tree,  
        CAST( c.value('text()[1]','NVARCHAR(MAX)') AS NVARCHAR(MAX) ) AS Value, c.query('.') AS this,  
        c.query('*') AS t,  
        CAST(p.Sort + CAST( (lvl + 1) * 1024 + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS VARBINARY(4)) AS VARBINARY(MAX) ) AS Sort,  
        CAST((lvl + 1) * 1024 + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS INT)  
FROM cte p  
CROSS APPLY p.t.nodes('*') b(c)), cte2 AS (  
                                            SELECT 
                                            lvl AS Depth,  
                                            Name AS NodeName,  
                                            ParentName, 
                                            ParentPosition, 
                                            NodeType,  
                                            FullPath,  
                                            XPath,  
                                            Position, 
                                            Tree AS TreeView,  
                                            Value,  
                                            this AS XMLData,  
                                            Sort, ID  
                                            FROM cte  
UNION ALL 
SELECT 
        p.lvl,  
        x.value('local-name(.)','NVARCHAR(MAX)'),  
        p.Name, 
        p.Position, 
        CAST(N'Attribute' AS NVARCHAR(20)),  
        p.FullPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
        p.XPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
        1, 
        SPACE(2 * p.lvl - 1) + N'|' + REPLICATE('-', 1)  
        + N'@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
        x.value('.','NVARCHAR(MAX)'),  
        NULL,  
        p.Sort,  
        p.ID + 1  
FROM cte p  
CROSS APPLY this.nodes('/*/@*') a(x)  
)  
SELECT 
        ROW_NUMBER() OVER(ORDER BY Sort, ID) AS ID,  
        ParentName, ParentPosition,Depth, NodeName, Position,   
        NodeType, FullPath, XPath, TreeView, Value, XMLData 
FROM cte2
于 2014-03-05T18:46:47.927 に答える
0

XML コンテンツでいっぱいのテーブルからすべての個別のタグ名をかなり簡単に抽出できるはずです。

DECLARE @input TABLE (ID INT, XmlCOntent XML)

INSERT INTO @input VALUES(1, '<array type="DWORD" name="m_somesetting.SMTPPorts" size="5"> 
   <set>19</set> 
   <set>1D0</set> 
   <set>14B</set> 
</array>'), 
(2, '<array2 type="DWORD" name="m_somesetting.SMTPPorts" size="5"> 
   <set2>19</set2> 
   <set3>1D0</set3> 
   <set4>14B</set4> 
</array2>')

SELECT
    DISTINCT 
    Nodes.value('local-name(.)', 'varchar(50)')
FROM
    @input
CROSS APPLY 
    XmlContent.nodes('//*') AS Tbl(Nodes)    

気をつけてください:私は簡単に言いました-すぐではありません。これでしばらく騒ぎます!しかし、それでもすべて手動で行うよりも優れています:-)

于 2012-10-28T13:12:58.323 に答える