从执行计划中粉碎XML

时间:2016-09-06 11:23:23

标签: sql sql-server xml tsql sql-execution-plan

我之前说过,我讨厌使用XML,可怕的东西,但有时是必要的。

我当前的问题是我试图从执行计划中获取XML(由用户提供,因此可以是任何大小)并将其粉碎成表格以供进一步操作。我现在有两种选择;

  1. 我可以计算出可用于执行计划的最大节点数量(我怀疑这将是很多)并创建可用于任何XML输入的整个脚本。这将是一次性事情,所以不是问题。
  2. 另一种方法是动态计算节点数量,并根据要求创建输出。
  3. 过去有没有人做过类似的练习?我发现的所有示例查询都已知道输出字段。

2 个答案:

答案 0 :(得分:6)

一种非常直接的方式(虽然arrayToDataTable是你的XML执行计划):

@x

结果(不是所有列)

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(为什么有),id=1允许区分元素,attributs和(浮动)文本。 nodetype列指向链中的兄弟姐妹。缺少的列与名称空间相关......

prev的方法已经过时,但这是极少有可能仍然非常有用的情况之一......

你得到一个包含你可能用递归CTE查询的ID和ParentID的列表......这取决于你之后想要做什么......

答案 1 :(得分:4)

使用路径和父项将XML分解为元素和属性的脚本。来自http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx

extension CGContext {
    func drawFlipped(image: CGImage, rect: CGRect) {
        saveGState()
        translateBy(x: 0, y: rect.height)
        scaleBy(x: 1, y: -1)
        draw(image, in: rect)
        restoreGState()
    }
}