查询(SQL Server)从存储为varchar(max)的XML列中的节点获取值?

时间:2016-06-15 21:29:15

标签: sql-server xml

我讨厌处理XML查询。我不经常这么做,以便记住如何格式化所有内容,但我的斗智尽头。 假设我有一个名为Messages的表,其中有一个名为Payload的列。 Payload包含存储为varchar(max)的XML。 XML的格式如下:

<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
  
<VID>3656183</VID>
  
</NCOAPACP>

如何查询表以检索VID节点中的值列表?

4 个答案:

答案 0 :(得分:0)

试试这个:

declare @w as xml = cast('
<NCOAPACP xmlns:i=''http://www.w3.org/2001/XMLSchema-instance''
 xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">

 <VID>3656183</VID>

 </NCOAPACP>' as xml)


 SELECT @w.value('declare namespace ns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM";
                   ns:NCOAPACP[1]/ns:VID[1]','varchar(10)') AS VID

如果您有多个VID节点,可以尝试:

declare @w as xml = cast('
    <NCOAPACP xmlns:i=''http://www.w3.org/2001/XMLSchema-instance''
xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">

<VID>3656183</VID>
<VID>454545</VID>

</NCOAPACP>' as xml)


 SELECT VID.value('.','varchar(10)')
 from @w.nodes(
    'declare namespace ns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM";
    ns:NCOAPACP[1]/ns:VID'
    ) 
    AS C(VID)

答案 1 :(得分:0)

如果XML数据在表列中,那么解决方案会更棘手。特别是如果数据类型为varchar(max)

declare @tbl table(id int,payload varchar(max))--sample table
--sample data
insert @tbl values 
(1,'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
<VID>3656184</VID>
</NCOAPACP>'),
(2,'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>123456</VID>
<VID>987654</VID>
</NCOAPACP>')

 --it is convenient to define namespaces before the query
;with xmlnamespaces('uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM' as x)--we will use this x:
select id, t.vid.value('.[1]','varchar(20)') vid 
-- . means self. [1] ensure single value
from 
--convert varchar(max) to xml first
(select id,cast(payload as xml) payload from @tbl) tt
cross apply
--convert xml to a tabular form
tt.payload.nodes('//x:VID') t(vid)

结果:

id  vid
1   3656183
1   3656184
2   123456
2   987654

答案 2 :(得分:0)

你可以试试这个

DECLARE @Messages TABLE(ID INT, Payload NVARCHAR(MAX))
INSERT INTO @Messages(ID, Payload) VALUES(1, '<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"> <VID>3656183</VID> </NCOAPACP>')
INSERT INTO @Messages(ID, Payload) VALUES(2, '<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"> <VID>3656183</VID> <VID>3656184</VID> </NCOAPACP>')

;WITH CTE(ID, Payload) AS
(
    SELECT ID, CAST(Payload AS XML) 
    FROM @Messages
)
SELECT
ID, 
x.items.value('.', 'NVARCHAR(10)')
FROM CTE
CROSS APPLY Payload.nodes('declare namespace xx="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"; xx:NCOAPACP/xx:VID') as x(items)

答案 3 :(得分:0)

最简单的方法(CTE test创建只是为了获得输出,您的xml值转换为varchar(max),如表中所示,然后是SELECT *.value):

;WITH test AS (
SELECT CAST(
'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">

<VID>3656183</VID>

</NCOAPACP>' as varchar(max)) as Payload
)

SELECT CAST(Payload as xml).value('(/*/*)[1]', 'int')
FROM test

输出:

3656183