Sql server 在SQL Server中将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文档的以下部分:

    <?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);