由于这个 XML,您无法正确解析它。您需要更改它 - 您应该将每个项目及其itemid子项目放入一个单独的节点中 - 否则您的主节点下<item>只有一个长长的节点列表<itemid>,但您无法判断哪些节点属于一起.. ..<subitems><items><itemid><subitems>
您需要将 XML 更改为如下所示:
<job>
<jobid>4711</jobid>
<items>
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
... (possibly more <item> nodes) ....
</items>
</job>
那么您可以使用与您上一个问题基本相同的代码 - 扩展到涵盖三个级别:
CREATE PROCEDURE dbo.SaveJobs (@input XML)
AS BEGIN
;WITH JobsData AS
(
SELECT
JobID = JobNode.value('(jobid)[1]', 'int'),
ItemID = ItemNode.value('(itemid)[1]', 'int'),
SubItemID = SubItemNode.value('.', 'int')
FROM
@input.nodes('/jobs/job') AS TblJobs(JobNode)
CROSS APPLY
JobNode.nodes('items/item') AS TblItems(ItemNode)
CROSS APPLY
ItemNode.nodes('subitems/subitem') AS TblSubItems(SubItemNode)
)
INSERT INTO dbo.tblDummy(JobID, ItemID, SubItemID)
SELECT JobID, ItemID, SubItemID
FROM JobsData
END
基本上,您需要三个 XML 节点“列表”:
- 首先你需要所有
<jobs>/<job>节点的列表来获取jobid值
- 对于每个作业节点,您还需要获取它们的嵌套列表
<items>/<item>以获取itemid值
- 从每个节点,您还可以获得
<subitems>/<subitem>
这很可能会起作用 - 但很可能会相当慢(对.nodes()函数的三个嵌套调用!)。
更新:
好的,所以第一个调用@input.nodes('/jobs/job') AS TblJobs(JobNode)基本上创建了一个TblJobs具有单列的“伪”表,JobNode并且您的 XML 中的每个<job>元素都被存储到该伪表中的一行中 - 所以第一行将在其JobNode列中包含此 XML:
<job>
<jobid>4711</jobid>
<items>
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
... (possibly more <item> nodes) ....
</items>
</job>
并且每一行将包含<job>内部每个后续元素的附加 XML 片段<jobs>
从这些 XML 片段中的每一个,第二个调用
CROSS APPLY JobNode.nodes('items/item') AS TblItems(ItemNode)
再次选择一个XML片段列表到一个伪TblItems表(ItemNode<item><job>
所以这个伪表的第一行包含:
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
第二行将包含
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
等等。
然后第三次调用——您已经猜到了——再次将 XML 元素列表作为行提取到伪表<subitem>中——XML 片段中的每个节点都有一个条目。
更新#2:
我是“JobID = JobNode.value('(jobid)[1]', 'int')” 代码行的新手
好的 - 给定<Job>您拥有的 XML 片段:
<job>
<jobid>4711</jobid>
<items>
......
</items>
</job>
该.value()调用只是在那个 XML 上执行这个 XPath 表达式 ( jobid) 并基本上取回<jobid>4711</jobid>片段。然后它提取该节点的值(内部文本),.value()调用的第二个参数定义将其解释为什么 SQL 数据类型 - 所以它基本上4711从<jobid>节点中获取 并将其解释为int