Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

T-SQL lặp qua cột dữ liệu XML để lấy ra tập hợp các đường dẫn duy nhất

Phương pháp lỗi thời với FROM OPENXML có thể là một lựa chọn ở đây. Kiểm tra câu trả lời này .

Tại liên kết này bạn sẽ tìm thấy một hàm mà John Cappelletti đã đăng thường xuyên, hàm này sẽ chia nhỏ bất kỳ XML nào (phần ghi có bên dưới mã của hàm).

Nhưng tôi không chắc, những gì bạn đang thực sự cố gắng đạt được ... Tại sao bạn cần con đường? Nếu bạn quan tâm đến giá trị của tất cả các nút mục tiêu, bạn có thể làm như thế này (tìm kiếm sâu với // không cần XPath chính xác )

 SELECT t.value(N'(text())[1]','nvarchar(max)')
 FROM @xml.nodes('//target') AS A(t);

Nếu bạn thực sự cần tất cả và mọi thứ bạn có thể kiểm tra điều này:

CREATE FUNCTION [dbo].[udf-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

Taken from John Cappelletti: https://stackoverflow.com/a/42729851/5089204

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

DECLARE @xml XML=
'<log>
  <clients>
   <client>
    <section name ="Apps"> 
     <questions>
      <groupone>
       <question>
        <target>Age</target>
       </question>
       <question>
        <target> Height</target>
       </question>
       <question>
        <target> Weight</target>
       </question>
      </groupone>
      <grouptwo name = "exercise">
       <wording>what is your name</wording>
        <question>
         <id>1</id>
         <target>def</target>
        </question>
      </grouptwo>
     </questions>
    </section>
   </client>
  </clients>
 </log>';

 SELECT * FROM dbo.[udf-XML-Hier](@xml);
GO



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ứng dụng khách có địa chỉ IP không được phép truy cập vào cơ sở dữ liệu Azure SQL của máy chủ

  2. Khung thực thể và quan hệ (1 đến nhiều) - (nhiều đến 1) (1 - * * - 1)

  3. Tweet vui nhộn về cuộc đời của một DBA

  4. Các cách theo dõi cơ sở dữ liệu đã xóa trong SQL Server

  5. Thay thế lần xuất hiện đầu tiên của chuỗi con trong một chuỗi trong SQL