Sql server 在没有架构的SQL Server中查询XML
我有一个数据库,它存储了大量XML,其中包含有关我们公司产品的信息。没有为XML定义模式,也没有人拥有所有潜在标记的列表 每个记录都有数百个这样的结构:Sql server 在没有架构的SQL Server中查询XML,sql-server,xml,xquery,Sql Server,Xml,Xquery,我有一个数据库,它存储了大量XML,其中包含有关我们公司产品的信息。没有为XML定义模式,也没有人拥有所有潜在标记的列表 每个记录都有数百个这样的结构: <array type="DWORD" name="m_somesetting.SMTPPorts" size="5"> <set>19</set> <set>1D0</set> <set>14B</set> </array>
<array type="DWORD" name="m_somesetting.SMTPPorts" size="5">
<set>19</set>
<set>1D0</set>
<set>14B</set>
</array>
我被要求创建一个表,显示每个可能的标记一个值,以及数万条记录中有多少条具有该特定设置
有人知道我如何实现自动化吗?我对如何对XML进行查询有一个合理的理解,但我需要一些方法,首先获取存在的每个标记,然后获取存在的每个唯一值,最后获取包含该值的记录计数
如何将每个可能的标记简单地编码到查询中?您应该能够很容易地从一个充满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)
请注意:我说得很容易,但不是很快。这将是搅拌相当长一段时间!但这仍然比手工操作要好:使用UDF从xml创建表
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