我在SQL Server 2016中有一个临时表,它有许多XML数据。我需要的是获取每个XML,从中读取数据以输入另一个表并从临时表中删除数据。 但是,我有两个问题。一个是XML的架构不一致。对于一些人来说,可能会有额外的节点,而对于其他节点,它不会在那里。此外,对于每个XML,我必须循环多个消息以为主表创建多个行。其次,我已经尝试过使用“CROSS APPLY' (我可能错过了一些连接,但数据无论如何都会出现)结果是每20秒收到1条消息,尝试SSIS(再次缺少1-2个连接,但数据无论如何都会出现),结果是每8秒收到1条消息。最后,我创建了C#控制台代码,以便在datatable中获取消息,将其转换为XML文档,检查节点是否存在,根据需要进行循环,最后再次将其插入数据库,每秒大约需要3-4条消息。 / p>
现在我的问题是,我想让它更快(理想情况下每分钟1000条消息)。任何人都可以提出更好的方法来实现这个目标吗?
编辑:( XML看起来如下所示)
<Step1>
<MetaData>
<Node1>Value</Node1>
<Node2>Value</Node2>
</MetaData>
<ActualData>
<MainNode>
<Child1>
<NodeA>Value</NodeA>
</Child1>
<Child2>
<Numbers>
<Child a="b">LoopValue</Child>
<Optional a="b">AdditionalLoopValue</Optional>
</Numbers>
<Alphabets>
<Child a="b">
<Child1>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child1>
<Child2>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child2>
</Child>
<Optional a="b">
<Child1>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child1>
<Child2>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child2>
</Optional>
</Alphabets>
</Child2>
<Child3>
<Loop1>
<Child1>Value</Child1>
<Child2>
<Sub1>Value</Sub1>
</Child2>
<Child3>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child3>
<Child4>Value</Child4>
</Loop1>
<Loop2>
<Child1>Value</Child1>
<Child2>
<Sub1>Value</Sub1>
</Child2>
<Child3>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Child3>
<Child4>Value</Child4>
<Optional1>
<Sub1>Value</Sub1>
<Sub2>Value</Sub2>
</Optional1>
</Loop2>
</Child3>
</MainNode>
</ActualData>
</Step1>
编辑2 :(代码如下所示)
string a,b,c;
DataTable dt;
foreach on DataTable.Rows
{ foreach node on nodelist
{ if Node1.ChildNode !=null
{a=Node1.ChildNode["NodeName"]}
if Node1.ChildNode !=null
{b=Node1.ChildNode["NodeName"]}
for loop on b
{if Node1.ChildNode != null
{c=Node1.ChildNode["NodeName"]}
dt.Rows.Add(a,b,c);}}
delete from temp table based on id.
add records from dt to main table
dt.Rows.Clear();}
答案 0 :(得分:0)
public string str { get; private set; }
private void RecursiveSearchInXmlWithString(XmlNode xmlnode, string nametofind)
{
// check if node has children, if so then it recursively search the children too
if (xmlnode.HasChildNodes)
{
for (int i = 0; i < xmlnode.ChildNodes.Count; i++)
{
RecursiveSearchInXmlWithString(xmlnode.ChildNodes[i], nametofind);
}
}
// here is the element that we are searching for
if (xmlnode.Name == nametofind)
{
str = xmlnode.InnerText;
}
}
我有一个resursive函数与这个类的公共全局变量。 str只捕获正确的值,调用后可以使用str。在每个节点之后,你必须捕获str。你可以在此之后搞清楚。
您还需要使用if语句处理所有可能的情况。
答案 1 :(得分:0)
如果这些XML很大并且你有很多这样的XML,那么将数据转移到你的C#应用程序并创建一个XML文档以便阅读它需要花费大量的时间。如果该列是本机XML列,那么在SQL-Server中完成此工作将会快得多。
您的XML是深层嵌套的。我希望,在任何情况下你都可以依赖某种结构。
只是暗示你可以如何继续:
SELECT @xml.value(N'(/Step1/MetaData/Node1/text())[1]',N'nvarchar(max)') AS Meta1
,@xml.value(N'(/Step1/MetaData/Node2/text())[1]',N'nvarchar(max)') AS Meta2
,childNode.value(N'local-name(.)','nvarchar(max)') AS ChildNode
,lvl2Numbers.value(N'(Child/@a)[1]',N'nvarchar(max)') AS NumberChildA
,lvl2Numbers.value(N'(Child/text())[1]',N'nvarchar(max)') AS NumberChildText
,lvl2Numbers.value(N'(Optional/@a)[1]',N'nvarchar(max)') AS NumberOptionalA
,lvl2Numbers.value(N'(Optional/text())[1]',N'nvarchar(max)') AS NumberOptionalText
,lvl2Alpha.query(N'.') AS lvl2Alpha
--add further levels here
,lvl2Loop.query(N'.') AS lvl2Loop
--add further levels here
FROM @xml.nodes(N'/Step1/ActualData/MainNode/*') AS A(childNode)
OUTER APPLY childNode.nodes(N'*[local-name()="Numbers"]') AS B1(lvl2Numbers)
OUTER APPLY childNode.nodes(N'*[local-name()="Alphabets"]') AS B2(lvl2Alpha)
OUTER APPLY lvl2Alpha.nodes(N'Child') AS B2a(ChildrenOfAlpha)
OUTER APPLY ChildrenOfAlpha.nodes(N'*') AS B2aa(SubChildrenOfAlpha)
OUTER APPLY SubChildrenOfAlpha.nodes(N'*') AS B2ab(SubsInSubChildrenOfAlpha)
OUTER APPLY lvl2Alpha.nodes(N'Optional') AS B2b(OptionalOfAlpha)
OUTER APPLY OptionalOfAlpha.nodes(N'*') AS B2ba(SubOptionalOfAlpha)
OUTER APPLY SubOptionalOfAlpha.nodes(N'*') AS B2bb(SubsInSubOptionalOfAlpha)
OUTER APPLY childNode.nodes(N'*[substring(local-name(),1,4)="Loop"]') AS B3(lvl2Loop)
--and so on
通过这样的查询,您可以逐步降低层次结构,并在非规范化的宽表中返回整个所有。但这不会很快......
我为每种数据结构创建一个查询,并使用T-SQL
作为逻辑,或使用.query()
调用并将此结果加载到C#中以处理那里的小片段。
如果此XML的构造在您的控制之下,请尝试避免使用名称编号的元素(<Child1>, <Child2> ...
)如果需要,请将其更改为<Child nr="1">, <Child nr="2"> ...
- 更好并且更快阅读...