0

我有以下 XML,我希望将其数据保存在我的 SQL 表中。我有一个名为 tblDummy 的表,它有三列“JobID”“ItemID”“SubitemID”。Jobid 和 Itemid 的特定组合可以有多个 subitemsid。我怎样才能做到这一点?

<jobs>
   <job>
     <jobid>4711</jobid>
     <items>
     <itemid>1</itemid>
       <subitems>
        <subitemid>1</subitemid>
        <subitemid>2</subitemid>
       </subitems>
    <itemid>2</itemid>
       <subitems>
        <subitemid>7</subitemid>
        <subitemid>10</subitemid>
       </subitems>
    <itemid>9</itemid>
       <subitems>
        <subitemid>12</subitemid>
        <subitemid>16</subitemid>
       </subitems>
    </items>
   </job>  
 </jobs>
4

2 回答 2

1

由于这个 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

于 2012-06-17T08:04:08.760 回答
0

您可以将 Jobid 和 Itemid 的组合键作为主键。

于 2012-06-17T08:05:05.630 回答