简体   繁体   English

使用开放的xml或xml函数SQL读取重复标签

[英]Reading repeating tags using open xml or xml functions SQL

<ActiveDig>
    <Dig IsPrim="True">
        <Code>3342</Code>
        <Name>abc</Name>
    </Dig>
    <Dig IsPrim="False">
        <Code>5342</Code>
        <Name>xyz</Name>
    </Dig>
</ActiveDig>

I'm trying to load it into table as follows: 我正在尝试将其加载到表中,如下所示:

| Dig_Isprim  |  Code  |  Name  |
|-------------|--------|--------|
|  True       |  3342  |   abc  |
|-------------|--------|--------|
|  False      |  5342  |   xyz  |

Example

Set @XML ='
<ActiveDig>
    <Dig IsPrim="True">
        <Code>3342</Code>
        <Name>abc</Name>
    </Dig>
    <Dig IsPrim="False">
        <Code>5342</Code>
        <Name>xyz</Name>
    </Dig>
</ActiveDig>
'

Select Dig_Isprim = lvl1.n.value('@IsPrim','varchar(50)') 
      ,Code       = lvl1.n.value('./Code[1]','varchar(50)') 
      ,Name       = lvl1.n.value('./Name[1]','varchar(50)') 
 From  @XML.nodes('ActiveDig/*')  lvl1(n)

Returns 退货

Dig_Isprim  Code    Name
True        3342    abc
False       5342    xyz

EDIT -FULLY DYNAMIC SQL 编辑-完全动态SQL

The following uses a Table-Valued Function to parse virtually any XML into a dataset. 下面使用表值函数将几乎所有XML解析为数据集。 Then we have some Dynamic XML within some Dynamic XML. 然后,我们在一些动态XML中包含一些动态XML。

It may seem a little complicated, but when you look at the individual parts, it is not so bad. 看起来似乎有些复杂,但是当您查看各个部分时,还不错。

Example

Declare @XML xml ='
<ActiveDig>
    <Dig IsPrim="True">
        <Code>3342</Code>
        <Name>abc</Name>
    </Dig>
    <Dig IsPrim="False">
        <Code>5342</Code>
        <Name>xyz</Name>
    </Dig>
</ActiveDig>
'


Declare @SQL varchar(max) = '
Select * Into #Temp 
 From (
        Select *
              ,Item = concat(Element,IIF(Attribute='''','''',''_''),Attribute )
              ,RowN = sum(case when Lvl=2 then 1 else 0 end) over (Order by R1)
         From  [dbo].[tvf-XML-Hier](cast('''+cast(@XML as varchar(max))+''' as xml))  
      ) A
 Where Value is not null 

Declare @SQL varchar(max) = ''
Select *
 From ( Select RowN,Item,Value From  #Temp ) A
 Pivot (max([Value]) For [Item] in ('' + Stuff((Select Top 1000 '',''+QuoteName(Item) From (Select Distinct Item,Seq=min(R1) over (Partition By Item) from #Temp ) A Order By Seq For XML Path('''')),1,1,'''')  + '') ) p''
Exec(@SQL);

'
Exec(@SQL)

Returns 退货

在此处输入图片说明

You may notice the only thing specified is Lvl 2... No attribute names or Node Names. 您可能会注意到,唯一指定的内容是Lvl 2 ...没有属性名称或节点名称。

The UDF if Interested UDF(如果有兴趣)

CREATE FUNCTION [dbo].[tvf-XML-Hier](@XML xml)

Returns Table 
As Return

with  cte0 as ( 
                  Select Lvl       = 1
                        ,ID        = Cast(1 as int) 
                        ,Pt        = Cast(NULL as int)
                        ,Element   = x.value('local-name(.)','varchar(150)')
                        ,Attribute = cast('' as varchar(150))
                        ,Value     = x.value('text()[1]','varchar(max)')
                        ,XPath     = cast(concat(x.value('local-name(.)','varchar(max)'),'[' ,cast(Row_Number() Over(Order By (Select 1)) as int),']') as varchar(max))
                        ,Seq       = cast(1000000+Row_Number() over(Order By (Select 1)) as varchar(max))
                        ,AttData   = x.query('.') 
                        ,XMLData   = x.query('*') 
                  From   @XML.nodes('/*') a(x) 
                  Union  All
                  Select Lvl       = p.Lvl + 1 
                        ,ID        = Cast( (Lvl + 1) * 1024 + (Row_Number() Over(Order By (Select 1)) * 2) as int ) * 10
                        ,Pt        = p.ID
                        ,Element   = c.value('local-name(.)','varchar(150)')
                        ,Attribute = cast('' as varchar(150))
                        ,Value     = cast( c.value('text()[1]','varchar(max)') as varchar(max) ) 
                        ,XPath     = cast(concat(p.XPath,'/',c.value('local-name(.)','varchar(max)'),'[',cast(Row_Number() Over(PARTITION BY c.value('local-name(.)','varchar(max)') Order By (Select 1)) as int),']') as varchar(max) )
                        ,Seq       = cast(concat(p.Seq,' ',10000000+Cast( (Lvl + 1) * 1024 + (Row_Number() Over(Order By (Select 1)) * 2) as int ) * 10) as varchar(max))
                        ,AttData   = c.query('.') 
                        ,XMLData   = c.query('*') 
                  From   cte0 p 
                  Cross  Apply p.XMLData.nodes('*') b(c) 
              )
    , cte1 as (   
                  Select R1 = Row_Number() over (Order By Seq),A.*
                  From  (
                          Select  Lvl,ID,Pt,Element,Attribute,Value,XPath,Seq From cte0
                          Union All
                          Select Lvl       = p.Lvl+1
                                ,ID        = p.ID + Row_Number() over (Order By (Select NULL)) 
                                ,Pt        = p.ID
                                ,Element   = p.Element
                                ,Attribute = x.value('local-name(.)','varchar(150)')
                                ,Value     = x.value('.','varchar(max)')
                                ,XPath     = p.XPath + '/@' + x.value('local-name(.)','varchar(max)')
                                ,Seq       = cast(concat(p.Seq,' ',10000000+p.ID + Row_Number() over (Order By (Select NULL)) ) as varchar(max))
                          From   cte0 p 
                          Cross  Apply AttData.nodes('/*/@*') a(x) 
                        ) A 
               )

Select A.R1
      ,R2  = IsNull((Select max(R1) From cte1 Where Seq Like A.Seq+'%'),A.R1)
      ,A.Lvl
      ,A.ID
      ,A.Pt
      ,A.Element
      ,A.Attribute
      ,A.XPath
      ,Title = Replicate('|---',Lvl-1)+Element+IIF(Attribute='','','@'+Attribute)
      ,A.Value
 From  cte1 A

/*
Source: http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx

Declare @XML xml='<person><firstname preferred="Annie" nickname="BeBe">Annabelle</firstname><lastname>Smith</lastname></person>'
Select * from [dbo].[tvf-XML-Hier](@XML) Order by R1
*/

EDIT 2- Just to help with the Visualization 编辑2-只是为了帮助可视化

If you were to simply run the following: 如果您只需要运行以下命令:

Select * From [dbo].[tvf-XML-Hier](@XML) Order By R1

The Results would Be 结果将是

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM