我有以下XML,我希望将其数据保存在我的SQL表中。我有一个名为tblDummy的表,它有三列“JobID”“ItemID”“SubitemID”。对于Jobid和Itemid的特定组合,可以有多个子项。我怎么能这样做?
<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>
答案 0 :(得分: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>
<jobs>
元素的其他XML片段
从每个XML片段中,第二个调用
CROSS APPLY JobNode.nodes('items/item') AS TblItems(ItemNode)
再次选择一个XML片段列表到一个伪表(TblItems
),其中包含一列ItemNode
,其中包含<item>
内<job>
个节点的XML片段我们目前正在处理的节点。
因此伪表中的第一行包含:
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
,第二行将包含
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
等等。
然后第三个调用 - 你已经猜到了 - 再次将XML元素列表作为行提取到伪表中 - XML片段中每个<subitem>
节点的一个条目。
更新#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数据类型 - 因此它基本上抓取了{{ 1}}来自4711
节点,并将其解释为<jobid>
答案 1 :(得分:0)
您可以将Jobid和Itemid的复合键作为主键。