Sql server 在SQL Server中将xml中的不同元素放入一列
我有XML文档的以下部分:Sql server 在SQL Server中将xml中的不同元素放入一列,sql-server,xml,tsql,sql-server-2012,xquery,Sql Server,Xml,Tsql,Sql Server 2012,Xquery,我有XML文档的以下部分: <?xml version="1.0" encoding="ISO-8859-1" ?> <IPCScheme xmlns="http://depatisnet.dpma.de/ipc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://depatisnet.dpma.de/ipc ipc_scheme_3-1_dpma.x
<?xml version="1.0" encoding="ISO-8859-1" ?>
<IPCScheme xmlns="http://depatisnet.dpma.de/ipc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://depatisnet.dpma.de/ipc ipc_scheme_3-1_dpma.xsd" edition="20190101" lang="EN">
<ipcEntry symbol="A01D0000000000" kind="u" entryType="K">
<textBody><title>
<titlePart>
<text> HARVESTING </text>
</titlePart>
<titlePart>
<text> MOWING</text>
</titlePart>
</title></textBody>
</ipcEntry>
<ipcEntry symbol="A01F0000000000" kind="u" entryType="K">
<textBody><title>
<titlePart>
<text> THRESHING</text>
<entryReference> combines
<sref ref="A01D0041000000"></sref>
</entryReference>
</titlePart>
<titlePart>
<text> BALING OF STRAW, HAY OR THE LIKE</text>
</titlePart>
<titlePart>
<text> STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES</text>
</titlePart>
<titlePart>
<text> CUTTING OF STRAW, HAY OR THE LIKE</text>
</titlePart>
<titlePart>
<text> STORING AGRICULTURAL OR HORTICULTURAL PRODUCE</text>
<entryReference> arrangements for making or setting stacks in connection with harvesting
<sref ref="A01D0085000000"></sref>
</entryReference>
</titlePart>
</title></textBody>
</ipcEntry>
<ipcEntry symbol="A01B0000000000" kind="u" entryType="K">
<textBody><title>
<titlePart>
<text> SOIL WORKING IN AGRICULTURE OR FORESTRY</text>
</titlePart>
<titlePart>
<text> PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL</text>
<entryReference> making or covering furrows or holes for sowing, planting or manuring
<sref ref="A01C0005000000"></sref>
</entryReference>
<entryReference> machines for harvesting root crops
<sref ref="A01D0000000000"></sref>
</entryReference>
<entryReference> mowers convertible to soil working apparatus or capable of soil working
<sref ref="A01D0042040000"></sref>
</entryReference>
<entryReference> mowers combined with soil working implements
<sref ref="A01D0043120000"></sref>
</entryReference>
<entryReference>soil working for engineering purposes
<sref ref="E01"></sref> ,
<sref ref="E02"></sref> ,
<sref ref="E21"></sref>
</entryReference>
</titlePart>
</title></textBody>
</ipcEntry>
</IPCScheme>
我已经做了一个查询,它排除了最后一个分隔符,并且在条目引用时只包含括号,因此在没有条目引用的符号中没有“()”符号。但为了保持简单,因为问题是将查询本身包括在内,我在下面的查询中保留了这一部分
DECLARE @xml XML
Select @xml =P
FROM OPENROWSET (BULK 'C:\Users\File.xml', SINGLE_BLOB) AS Products(P)
;WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc',
'http://www.w3.org/2001/XMLSchema-instance' as xsi)
SELECT
MY_XML.IPC.value('@symbol', 'NVARCHAR(max)') as Symbol,
concat(left(MY_XML.IPC.query('for $i in textBody/title/titlePart/text return concat($i, ";")').value('.','NVARCHAR(max)'), len(MY_XML.IPC.query('for $i in textBody/title/titlePart/text return concat($i, ";")').value('.','NVARCHAR(max)'))-1),' (',My_XML.IPC.query('for $i in textBody/title/titlePart/entryReference return concat($i, ($i/sref/@ref)[1] , ";")').value('.','NVARCHAR(max)'),')') as String
FROM @xml.nodes('IPCScheme/ipcEntry/ipcEntry/ipcEntry') MY_XML(IPC)
结果是:
Symbol String
A01B0000000000 SOIL WORKING IN AGRICULTURE OR FORESTRY; PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL (making or covering furrows or holes for sowing, planting or manuring A01C0005000000; ; machines for harvesting root crops A01D0000000000; mowers convertible to soil working apparatus or capable of soil working A01D0042040000; mowers combined with soil working implements A01D0043120000; soil working for engineering purposes , , E01;)
A01D0000000000 HARVESTING; MOWING ()
A01F0000000000 THRESHING; BALING OF STRAW, HAY OR THE LIKE; STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES; CUTTING OF STRAW, HAY OR THE LIKE; STORING AGRICULTURAL OR HORTICULTURAL PRODUCE (combines A01D0041000000; arrangements for making or setting stacks in connection with harvesting A01D0085000000;)
因此,所有entryReferences都是通过构造添加到文本末尾的,当entryReferences添加到最后一个titlePart时,这是正确的,但不是一般的,此外,我只需要包含一个sref/@ref。我需要的是某种查询,它查询每个titlePart的不同元素,并以我喜欢的方式将其添加到整个字符串中我希望如此
编辑:
总而言之,我希望每个IPCCentry都有一个属性符号,每个IPCCentry都有一个组合文本,每个titlePart都有元素文本,后跟“(“entryReference和属性@ref from sref,后跟”);”和下一个titlePart。所有元素都可以有多个文本、entryReference或sref,这在某种程度上使其具有挑战性。xml片段后面的第一个表就是我想要的。sql代码之后的第二个表就是我得到的
希望你能对此有一些想法。提前谢谢
由@Shnugo略微编辑的解决方案
;WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
(
SELECT CONCAT('; ',B.tp.value('(text/text())[1]','nvarchar(100)'))
,CASE WHEN B.tp.exist('entryReference')=1 THEN
CONCAT(' ('
,STUFF(
(
SELECT CONCAT('; ',C.er.value('text()[1]','nvarchar(100)'))
,CASE WHEN C.er.exist('sref')=1 THEN
STUFF(
(
Select Concat(', ', D.ad.value('@ref[1]','nvarchar(100)'))
From C.er.nodes('sref') D(ad)
For XML PATH('')
),1,2,'') End
FROM B.tp.nodes('entryReference') C(er)
FOR XML PATH('')
),1,2,'')
,')') END
FROM A.entr.nodes('textBody/title/titlePart') B(tp)
FOR XML PATH('')
),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
有很多方法可以解决这个问题: 假设XML被读入XML类型的变量(提示:去掉
声明):
--这将使用嵌套的FOR XML PATH(“”)
来模拟分组连接,并使用STUFF()
来切掉前面的代码>
--优点:我可以轻松地使用TRIM()
(LTRIM()
和RTRIM()
在旧版本中)
--这与上面的方法大致相同,但使用XQuery的FLWOR方法:
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
entr.query('for $t in ./textBody/title/titlePart/text/text()
return <t>{concat(";",$t)}</t>')
.value('.','nvarchar(max)'),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
抱歉,我应该更仔细地阅读你自己的尝试。。。
您可以尝试以下方法来获得组合值:
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
(
SELECT CONCAT('; ',TRIM(B.tp.value('(text/text())[1]','nvarchar(100)')))
,CASE WHEN B.tp.exist('entryReference')=1 THEN
CONCAT(' ('
,STUFF(
(
SELECT CONCAT('; ',TRIM(C.er.value('text()[1]','nvarchar(100)')))
FROM B.tp.nodes('entryReference') C(er)
FOR XML PATH('')
),1,2,'')
,')') END
FROM A.entr.nodes('textBody/title/titlePart') B(tp)
FOR XML PATH('')
),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
遗憾的是,在XQuery FLWOR中,我们没有normalize-space()
或trim()
,因此嵌入的空格会将其放大
上面的解决方案使用了一个案例,当仅将()
添加到标题部分,其中至少有一个
您可以发布有效的xml吗?我将您的示例复制到我机器上的xml文件中,并运行了您的代码。“Msg 9410,16级,状态1,第2行XML解析:第38行,字符50,需要空白”@SeanLange行:
。。。在“u”和“entryType=“K”之间加一个空格……例如,“u”后面加一个空格“在这个例子中^^^^你的问题措辞非常混乱。你能提供这个XML片段的预期结果吗?@AlanBurstein你说得对。我编辑了xml片段,现在应该可以了。很抱歉没有再次测试它。@RogerWolf这是我的第一次测试,所以是的,肯定还有很长的路要走。我希望结果在xml片段后面的表中。使用我发布的代码,我只得到sql代码后面的表。我需要同时查询text和entryReference元素以及sref属性,但我只能单独查询。谢谢您的回答。我使用的是2012版。我不仅需要文本元素,还需要括号中带有sref/@ref的entryReference元素,就像xml片段后面的第一个表中一样。这非常适合。我还需要sref元素中的属性,但我只是在更新的代码中添加了另一个级别。我想我不能在我的版本中使用修剪功能,但这一点都没有问题。一开始它看起来不是很直观,但我想我会处理好的。我在问题中添加了我的完整代码。谢谢!
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,entr.query('data(.//text)').value('.','nvarchar(max)') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
(
SELECT CONCAT('; ',TRIM(t.value('text()[1]','nvarchar(100)')))
FROM entr.nodes('./textBody/title/titlePart/text') B(t)
FOR XML PATH('')
),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
entr.query('for $t in ./textBody/title/titlePart/text/text()
return <t>{concat(";",$t)}</t>')
.value('.','nvarchar(max)'),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
,cte AS
(
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,t.value('text()[1]','nvarchar(max)') AS TextNode
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr)
CROSS APPLY A.entr.nodes('./textBody/title/titlePart/text') B(t)
)
SELECT Symbol
,STRING_AGG(TextNode,';')
FROM cte
GROUP BY Symbol;
WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
,STUFF(
(
SELECT CONCAT('; ',TRIM(B.tp.value('(text/text())[1]','nvarchar(100)')))
,CASE WHEN B.tp.exist('entryReference')=1 THEN
CONCAT(' ('
,STUFF(
(
SELECT CONCAT('; ',TRIM(C.er.value('text()[1]','nvarchar(100)')))
FROM B.tp.nodes('entryReference') C(er)
FOR XML PATH('')
),1,2,'')
,')') END
FROM A.entr.nodes('textBody/title/titlePart') B(tp)
FOR XML PATH('')
),1,1,'') AS ConcatenatedTextNodes
FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);