I have following XML, and i wish to save its data in my SQL table. I have a table named as tblDummy it has three columns "JobID" "ItemID" "SubitemID". there can be multiple subitemsid for particular combination of Jobid and Itemid. How can i do this?
我有以下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>
2 个解决方案
#1
1
As this XML is, you cannot properly parse it. You would need to change it - you should put each item with its itemid
and subitems into a separate <item>
node - otherwise you just have a long list of <itemid>
and <subitems>
nodes under your <items>
main node, but you have no means of telling which <itemid>
and <subitems>
nodes belong together ....
就像这个XML一样,你无法正确地解析它。您需要更改它 - 您应该将每个项目及其itemid和子项目放入一个单独的
You need to change your XML to be something like this:
您需要将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>
THEN you could use basically the same code I had for your previous question - extended to cover three levels:
那么你可以使用与我之前的问题基本相同的代码 - 扩展到涵盖三个级别:
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
Basically, you need three "lists" of XML nodes:
基本上,您需要三个XML节点“列表”:
- first you need the list of all
<jobs>/<job>
nodes to get thejobid
values -
首先,您需要所有
/ 节点的列表来获取jobid值 - for each of those job nodes, you will also need to get their list of nested
<items>/<item>
to get theitemid
value -
对于每个作业节点,您还需要获取嵌套
/ - 的列表以获取itemid值
- from each node, you then also get the list of
<subitems>/<subitem>
-
然后,您还可以从每个节点获取
/ 的列表
This will most likely work - but most likely, it will be rather slow (three nested calls to the .nodes()
function!).
这很可能会起作用 - 但很可能,它会相当慢(对.nodes()函数的三次嵌套调用!)。
Update:
更新:
OK, so the first call @input.nodes('/jobs/job') AS TblJobs(JobNode)
basically creates a "pseudo" table TblJobs
with a single column JobNode
and each <job>
element in your XML is being stored into a row in that pseudo table - so the first row will contain this XML in it's JobNode
column:
好的,所以第一次调用@input.nodes('/ jobs / job')AS TblJobs(JobNode)基本上创建了一个带有单列JobNode的“伪”表TblJobs,并且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>
and each further row will contain the additional XML fragments for each subsequent <job>
element inside <jobs>
并且每个其他行将包含
From each of those XML fragments, the second call
从每个XML片段,第二个调用
CROSS APPLY JobNode.nodes('items/item') AS TblItems(ItemNode)
again selects a list of XML fragments into a pseudo table (TblItems
) with a single column ItemNode
that contains the XML fragment for each <item>
node inside that <job>
node we're dealing with currently.
再次选择一个XML片段列表到一个伪表(TblItems)中,该列包含一个ItemNode列,该列包含我们当前正在处理的
So the first row in this pseudo-table contains:
所以这个伪表中的第一行包含:
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
and the second row will contain
第二行将包含
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
and so on.
等等。
And then the third call - you've guessed it - again extracts a list of XML elements as rows into a pseudo-table - one entry for each <subitem>
node in your XML fragment.
然后第三个调用 - 您已经猜到了 - 再次将XML元素列表作为行提取到伪表中 - XML片段中每个
Update #2:
更新#2:
I'm new to "JobID = JobNode.value('(jobid)[1]', 'int')" line of code
我是新手“JobID = JobNode.value('(jobid)[1]','int')”代码行
OK - given the <Job>
XML fragment that you have:
好的 - 给定您拥有的
<job>
<jobid>4711</jobid>
<items>
......
</items>
</job>
the .value()
call just executes this XPath expression (jobid
) on that XML and basically gets back the <jobid>4711</jobid>
snippet. It then extracts the value of that node (the inner text), and the second parameter of the .value()
call defines what SQL data type to interpret this as - so it basically grabs the 4711
from the <jobid>
node and interprets it as an int
.value()调用只是对该XML执行此XPath表达式(jobid),并基本上返回
#2
0
You can take a composite key of Jobid and Itemid as primary key.
您可以将Jobid和Itemid的组合键作为主键。
#1
1
As this XML is, you cannot properly parse it. You would need to change it - you should put each item with its itemid
and subitems into a separate <item>
node - otherwise you just have a long list of <itemid>
and <subitems>
nodes under your <items>
main node, but you have no means of telling which <itemid>
and <subitems>
nodes belong together ....
就像这个XML一样,你无法正确地解析它。您需要更改它 - 您应该将每个项目及其itemid和子项目放入一个单独的
You need to change your XML to be something like this:
您需要将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>
THEN you could use basically the same code I had for your previous question - extended to cover three levels:
那么你可以使用与我之前的问题基本相同的代码 - 扩展到涵盖三个级别:
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
Basically, you need three "lists" of XML nodes:
基本上,您需要三个XML节点“列表”:
- first you need the list of all
<jobs>/<job>
nodes to get thejobid
values -
首先,您需要所有
/ 节点的列表来获取jobid值 - for each of those job nodes, you will also need to get their list of nested
<items>/<item>
to get theitemid
value -
对于每个作业节点,您还需要获取嵌套
/ - 的列表以获取itemid值
- from each node, you then also get the list of
<subitems>/<subitem>
-
然后,您还可以从每个节点获取
/ 的列表
This will most likely work - but most likely, it will be rather slow (three nested calls to the .nodes()
function!).
这很可能会起作用 - 但很可能,它会相当慢(对.nodes()函数的三次嵌套调用!)。
Update:
更新:
OK, so the first call @input.nodes('/jobs/job') AS TblJobs(JobNode)
basically creates a "pseudo" table TblJobs
with a single column JobNode
and each <job>
element in your XML is being stored into a row in that pseudo table - so the first row will contain this XML in it's JobNode
column:
好的,所以第一次调用@input.nodes('/ jobs / job')AS TblJobs(JobNode)基本上创建了一个带有单列JobNode的“伪”表TblJobs,并且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>
and each further row will contain the additional XML fragments for each subsequent <job>
element inside <jobs>
并且每个其他行将包含
From each of those XML fragments, the second call
从每个XML片段,第二个调用
CROSS APPLY JobNode.nodes('items/item') AS TblItems(ItemNode)
again selects a list of XML fragments into a pseudo table (TblItems
) with a single column ItemNode
that contains the XML fragment for each <item>
node inside that <job>
node we're dealing with currently.
再次选择一个XML片段列表到一个伪表(TblItems)中,该列包含一个ItemNode列,该列包含我们当前正在处理的
So the first row in this pseudo-table contains:
所以这个伪表中的第一行包含:
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
and the second row will contain
第二行将包含
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
and so on.
等等。
And then the third call - you've guessed it - again extracts a list of XML elements as rows into a pseudo-table - one entry for each <subitem>
node in your XML fragment.
然后第三个调用 - 您已经猜到了 - 再次将XML元素列表作为行提取到伪表中 - XML片段中每个
Update #2:
更新#2:
I'm new to "JobID = JobNode.value('(jobid)[1]', 'int')" line of code
我是新手“JobID = JobNode.value('(jobid)[1]','int')”代码行
OK - given the <Job>
XML fragment that you have:
好的 - 给定您拥有的
<job>
<jobid>4711</jobid>
<items>
......
</items>
</job>
the .value()
call just executes this XPath expression (jobid
) on that XML and basically gets back the <jobid>4711</jobid>
snippet. It then extracts the value of that node (the inner text), and the second parameter of the .value()
call defines what SQL data type to interpret this as - so it basically grabs the 4711
from the <jobid>
node and interprets it as an int
.value()调用只是对该XML执行此XPath表达式(jobid),并基本上返回
#2
0
You can take a composite key of Jobid and Itemid as primary key.
您可以将Jobid和Itemid的组合键作为主键。