查询XML创建字段名称而不知道节点名称

时间:2012-07-22 23:33:30

标签: sql-server xml nodes sql-server-2012

如果我有一个包含XML字段类型的SQL SERVER 2012表。它可能包含的记录如下。

我已将问题简化为以下内容。

记录1:

ID_FIELD='nn1'

XML_FIELD=
<KNOWN_NAME_1>
    <UNKNOWN_NAME1>Some value</UNKNOWN_NAME1>
    <UNKNOWN_NAME2>Some value</UNKNOWN_NAME2>
  ... Maybe more ...
</KNOWN_NAME_1>

记录2:

ID_FIELD='nn2'

XML_FIELD=
<KNOWN_NAME_2>
  <UNKNOWN_NAME1>Some value</UNKNOWN_NAME1>
  <UNKNOWN_NAME2>Some value</UNKNOWN_NAME2>
  ... Maybe more unknown fields ...
</KNOWN_NAME_2>

我想输出非xml:

UNKNOWN_NAME1 | UNKNOWN_NAME2 | ETC
-----------------------------------
Some Value      Some value

对于已知的根值(即KNOWN_NAME_1)

即。如果我新建节点值(我没有),我可以

SELECT
  XMLData.Node.value('UNKNOWN_NAME1[1]', 'varchar(100)') ,
  XMLData.Node.value('UNKNOWN_NAME2[1],  'varchar(100)')
FROM FooTable
  CROSS APPLY MyXmlField.nodes('//KNOWN_NAME_1') XMLData(Node)
  -- WHERE SOME ID value = 'NN1' (all XML records have a separate id)

一切都很好但是我想在不知道节点名称的情况下为所有节点(未知数量)执行此操作。根将只包含它不会更深入的节点。

这在SQL中是否可行?

我看过这个,但我怀疑自己能否获得足够的权利来实施它。

http://architectshack.com/ClrXmlShredder.ashx

1 个答案:

答案 0 :(得分:2)

如果您不知道输出中的列名,则必须使用dynamic SQL

-- Source table
declare @FooTable table
(
  ID_FIELD char(3),
  XML_FIELD xml
)

-- Sample data
insert into @FooTable values
('nn1', '<KNOWN_NAME_1>
           <UNKNOWN_NAME1>Some value1</UNKNOWN_NAME1>
           <UNKNOWN_NAME2>Some value2</UNKNOWN_NAME2>
         </KNOWN_NAME_1>')

-- ID to look for
declare @ID char(3) = 'nn1'

-- Element name to look for
declare @KnownName varchar(100) = 'KNOWN_NAME_1'

-- Variable to hold the XML to process
declare @XML xml

-- Get the XML
select @XML = XML_FIELD
from @FooTable
where ID_FIELD = @ID

-- Variable for dynamic SQL
declare @SQL nvarchar(max)

-- Build the query
select @SQL = 'select '+stuff(
  (
  select ',T.N.value('''+T.N.value('local-name(.)', 'sysname')+'[1]'', ''varchar(max)'') as '+T.N.value('local-name(.)', 'sysname')
  from @XML.nodes('/*[local-name(.)=sql:variable("@KnownName")]/*') as T(N)
  for xml path(''), type
  ).value('.', 'nvarchar(max)'), 1, 1, '')+
  ' from @XML.nodes(''/*[local-name(.)=sql:variable("@KnownName")]'') as T(N)'

-- Execute the query
exec sp_executesql @SQL, 
     N'@XML xml, @KnownName varchar(100)', 
     @XML = @XML, 
     @KnownName = @KnownName

结果:

UNKNOWN_NAME1   UNKNOWN_NAME2
--------------- ---------------
Some value1     Some value2

动态生成的查询如下所示:

select T.N.value('UNKNOWN_NAME1[1]', 'varchar(max)') as UNKNOWN_NAME1,
       T.N.value('UNKNOWN_NAME2[1]', 'varchar(max)') as UNKNOWN_NAME2 
from @XML.nodes('/*[local-name(.)=sql:variable("@KnownName")]') as T(N)

SE-Data