복붙노트

[SQL] 실행 계획에서 XML을 파쇄

SQL

실행 계획에서 XML을 파쇄

나는 XML과 작업에 무서운 물건,하지만 필요 때로는 싫어한다는 말함으로써이 서문 것이다.

나의 현재 문제는 내가 실행 계획에서 XML 취하려고 해요 (사용자가 제공을하므로 크기가 될 수 있음) 추가 조작을위한 테이블에이 분쇄기는 것이다. 나는 순간에 두 가지 옵션까지 해요;

사람은 과거에 비슷한 운동을 수행 했습니까? 샘플 쿼리의 모든 이미 출력 필드를 알고 찾았습니다.

해결법

  1. ==============================

    1.(@x는 당신의 XML - 실행 - 계획 중에) 아주 똑 바른 방법이 될 수있다 :

    (@x는 당신의 XML - 실행 - 계획 중에) 아주 똑 바른 방법이 될 수있다 :

    DECLARE @x XML=
    N'<root>
        <ElementE1 AttributA1="A1-text belongs to E1[1]" OneMore="xyz">E1-Text 2</ElementE1>
        <ElementE1 AttributA1="A1-text belongs to E1[2]">E1-Text 2</ElementE1>
        <ElementParent>
          <subElement test="sub"/>
          Free text
        </ElementParent>
      </root>';
    
    DECLARE @idoc INT;
    EXEC sp_xml_preparedocument @idoc OUTPUT, @x;   
    SELECT * FROM OPENXML (@idoc, '*');   
    EXEC sp_xml_removedocument @idoc;  
    

    그 결과 (모든 열)

    +----+----------+----------+--------------+------+--------------------------+
    | id | parentid | nodetype | localname    | prev | text                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 0  | NULL     | 1        | root         | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 2  | 0        | 1        | ElementE1    | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 3  | 2        | 2        | AttributA1   | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 13 | 3        | 3        | #text        | NULL | A1-text belongs to E1[1] |
    +----+----------+----------+--------------+------+--------------------------+
    | 4  | 2        | 2        | OneMore      | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 14 | 4        | 3        | #text        | NULL | xyz                      |
    +----+----------+----------+--------------+------+--------------------------+
    | 5  | 2        | 3        | #text        | NULL | E1-Text 2                |
    +----+----------+----------+--------------+------+--------------------------+
    | 6  | 0        | 1        | ElementE1    | 2    | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 7  | 6        | 2        | AttributA1   | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 15 | 7        | 3        | #text        | NULL | A1-text belongs to E1[2] |
    +----+----------+----------+--------------+------+--------------------------+
    | 8  | 6        | 3        | #text        | NULL | E1-Text 2                |
    +----+----------+----------+--------------+------+--------------------------+
    | 9  | 0        | 1        | ElementParent| 6    | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 10 | 9        | 1        | subElement   | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 11 | 10       | 2        | test         | NULL | NULL                     |
    +----+----------+----------+--------------+------+--------------------------+
    | 16 | 11       | 3        | #text        | NULL | sub                      |
    +----+----------+----------+--------------+------+--------------------------+
    | 12 | 9        | 3        | #text        | 10   | Free text                |
    +----+----------+----------+--------------+------+--------------------------+
    

    이드 방송 명확 알고리즘 제 폭 즉, 거기에 ID = 1 (왜 적) 및 NODETYPE 요소, 및 attributs (플로팅) 텍스트를 구별 할 수있다.하지 A는 체인에 형제 이전에 열을 가리킨다. 누락 된 열은 네임 스페이스와 관련된 ...

    OPENXML FROM와 접근 방식은 구식이되어 있지만, 이것은 여전히 ​​유용 매우 될 수있는 드문 경우 중 하나입니다 ...

    당신이 당신이 나중에이 수행 할 작업에 따라 달라집니다 ... ID와 당신이 재귀 CTE로 조회 할 수 ParentIDs와 목록을 가져올 수 ...

  2. ==============================

    2.자신의 경로로 부모와 함께 요소와 속성에 이르기까지 조각 XML에 스크립트. http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx에서

    자신의 경로로 부모와 함께 요소와 속성에 이르기까지 조각 XML에 스크립트. http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx에서

    CREATE FUNCTION [dbo].[XMLTable]( 
        @x XML 
    ) 
    RETURNS TABLE 
    AS RETURN 
    /*---------------------------------------------------------------------- 
    This INLINE TVF uses a recursive CTE that processes each element and 
    attribute of the XML document passed in. 
    ----------------------------------------------------------------------*/ 
    WITH cte AS ( 
        /*------------------------------------------------------------------ 
        Anchor part of the recursive query. Retrieves the root element 
        of the XML document 
        ------------------------------------------------------------------*/ 
        SELECT 
            1 AS lvl, 
            x.value('local-name(.)','NVARCHAR(MAX)') AS Name, 
            CAST(NULL AS NVARCHAR(MAX)) AS ParentName,
            CAST(1 AS INT) AS ParentPosition,
            CAST(N'Element' AS NVARCHAR(20)) AS NodeType, 
            x.value('local-name(.)','NVARCHAR(MAX)') AS FullPath, 
            x.value('local-name(.)','NVARCHAR(MAX)') 
                + N'[' 
                + CAST(ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS NVARCHAR) 
                + N']' AS XPath, 
            ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS Position,
            x.value('local-name(.)','NVARCHAR(MAX)') AS Tree, 
            x.value('text()[1]','NVARCHAR(MAX)') AS Value, 
            x.query('.') AS this,        
            x.query('*') AS t, 
            CAST(CAST(1 AS VARBINARY(4)) AS VARBINARY(MAX)) AS Sort, 
            CAST(1 AS INT) AS ID 
        FROM @x.nodes('/*') a(x) 
        UNION ALL 
        /*------------------------------------------------------------------ 
        Start recursion. Retrieve each child element of the parent node 
        ------------------------------------------------------------------*/ 
        SELECT 
            p.lvl + 1 AS lvl, 
            c.value('local-name(.)','NVARCHAR(MAX)') AS Name, 
            CAST(p.Name AS NVARCHAR(MAX)) AS ParentName,
            CAST(p.Position AS INT) AS ParentPosition,
            CAST(N'Element' AS NVARCHAR(20)) AS NodeType, 
            CAST( 
                p.FullPath 
                + N'/' 
                + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX) 
            ) AS FullPath, 
            CAST( 
                p.XPath 
                + N'/' 
                + c.value('local-name(.)','NVARCHAR(MAX)') 
                + N'[' 
                + CAST(ROW_NUMBER() OVER(
                    PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)')
                    ORDER BY (SELECT 1)) AS NVARCHAR    ) 
                + N']' AS NVARCHAR(MAX) 
            ) AS XPath, 
            ROW_NUMBER() OVER(
                    PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)')
                    ORDER BY (SELECT 1)) AS Position,
            CAST( 
                SPACE(2 * p.lvl - 1) + N'|' + REPLICATE(N'-', 1)
                + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX) 
            ) AS Tree, 
            CAST( c.value('text()[1]','NVARCHAR(MAX)') AS NVARCHAR(MAX) ) AS Value, 
            c.query('.') AS this,        
            c.query('*') AS t, 
            CAST( 
                p.Sort 
                + CAST( (lvl + 1) * 1024 
                + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS VARBINARY(4) 
            ) AS VARBINARY(MAX) ) AS Sort, 
            CAST( 
                (lvl + 1) * 1024 
                + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS INT 
            ) 
        FROM cte p 
        CROSS APPLY p.t.nodes('*') b(c)        
    ), cte2 AS ( 
        SELECT 
            lvl AS Depth, 
            Name AS NodeName, 
            ParentName,
            ParentPosition,
            NodeType, 
            FullPath, 
            XPath, 
            Position,
            Tree AS TreeView, 
            Value, 
            this AS XMLData, 
            Sort, ID 
        FROM cte 
        UNION ALL 
        /*------------------------------------------------------------------ 
        Attributes do not need recursive calls. So add the attributes 
        to the query output at the end. 
        ------------------------------------------------------------------*/ 
        SELECT 
            p.lvl, 
            x.value('local-name(.)','NVARCHAR(MAX)'), 
            p.Name,
            p.Position,
            CAST(N'Attribute' AS NVARCHAR(20)), 
            p.FullPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'), 
            p.XPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'), 
            1,
            SPACE(2 * p.lvl - 1) + N'|' + REPLICATE('-', 1) 
                + N'@' + x.value('local-name(.)','NVARCHAR(MAX)'), 
            x.value('.','NVARCHAR(MAX)'), 
            NULL, 
            p.Sort, 
            p.ID + 1 
        FROM cte p 
        CROSS APPLY this.nodes('/*/@*') a(x) 
    ) 
    SELECT 
        ROW_NUMBER() OVER(ORDER BY Sort, ID) AS ID, 
        ParentName, ParentPosition,Depth, NodeName, Position,  
        NodeType, FullPath, XPath, TreeView, Value, XMLData
    FROM cte2;
    go
    SELECT * FROM dbo.XMLTable(' 
    <employees> 
        <emp name="jacob"/> 
        <emp name="steve"> 
            <phone>123</phone>
         some text                      
        </emp> 
    </employees> 
    ') 
    
  3. from https://stackoverflow.com/questions/39347880/shredding-xml-from-execution-plans by cc-by-sa and MIT license