如果我有一个包含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中是否可行?
我看过这个,但我怀疑自己能否获得足够的权利来实施它。
答案 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)