首先,我会说我讨厌 XML,这是一种可怕的东西,但有时是必要的。
我当前的问题是,我正在尝试从执行计划(由用户提供,因此可以是任何大小)中获取 XML,并将其分解到一个表中以供进一步操作。我现在只有两个选择;
- 我可以计算出可用于执行计划的最大节点数(我怀疑这会很多)并创建可用于任何 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
清楚地表明该算法是广度优先,没有id=1
(为什么永远如此)和nodetype
允许区分元素、属性和( float )文本。 prev
列指向链中的一个兄弟。缺少的列与命名空间有关...
FROM OPENXML
的方法已经过时,但这是它可能仍然非常有用的罕见情况之一...
您会得到一个包含 ID 和 ParentID 的列表,您可能会使用递归 CTE 查询...这取决于您之后想用它做什么...
关于sql - 从执行计划中分解 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39347880/