【问题标题】:How to import XML into a SQL Server database with C# which has parents如何使用具有父级的 C# 将 XML 导入 SQL Server 数据库
【发布时间】:2016-12-15 09:14:31
【问题描述】:

我有大约 100.000 个 xml 文件,每个文件包含 1 行数据(但它有 2 个父级)。

读取这些 XML 文件并将数据写入 SQL Server 表的最佳方法是什么?

这是我的 XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<recording>
    <dataformat>audio</dataformat>
    <starttime>2015-02-09 08:57:08:000 +0200</starttime>
    <endtime>2015-02-09 08:58:48:000 +0200</endtime>
    <nostart>false</nostart>
    <noend>false</noend>
    <recordingtype>stnbulk</recordingtype>
    <recordingline></recordingline>
    <servicename>005379763634</servicename>
    <servicenumber></servicenumber>
    <deliberatebreak>0</deliberatebreak>
    <calldirection>Outgoing</calldirection>
    <filename>890001000000003.wav</filename>
    <otherinum>0</otherinum>
    <callparty>1</callparty>
    <recordingowners>
        <recordingowner>131</recordingowner>
    </recordingowners>
    <parties>
        <party id="1">
            <number>131</number>
            <name>Santral131</name>
            <pstarttime>2015-02-09 08:58:48:912 +0200</pstarttime>
            <pendtime>2015-02-09 08:58:48:912 +0200</pendtime>
        </party>
        <party id="2">
            <number>005379763634</number>
            <pstarttime>2015-02-09 08:58:48:912 +0200</pstarttime>
            <pendtime>2015-02-09 08:58:48:912 +0200</pendtime>
        </party>
    </parties>
    <guids>
    </guids>
</recording>

我尝试通过使用XmlReader 将这些数据读取到数据集以插入到 SQL Server 数据库,但没有成功。

提前感谢您的支持。

【问题讨论】:

  • 也许尝试使用来自System.Xml.Linq 命名空间的XElement 类?

标签: c# sql-server xml


【解决方案1】:

这是一次性操作吗?文件名容易列出吗?文件名是否包含任何信息?所有 100k 文件的结构是否相同?

请提供您的表格的目标结构。

乍一看,最简单的方法是编写一个存储过程,接受XML 类型的参数。

您的 C# 应用程序使用 XmlDocument 直接从文件路径读取 XML,然后将 OuterXml 传递给 SP。该 SP 将读取 XML 并将其值插入到目标表中。将其作为字符串传递,不要传递声明 &lt;?xml ...?&gt;。 C# 隐式使用 unicode,T-SQL-XML 也是如此...

以下代码将为您提供每种类型元素的模板如何阅读它。在你的 SP 中使用这样的东西应该很容易(其中@xml 是传入的参数)。

注意:尽管生成了此 XML,但包含的日期时间值并未满足适当的格式 (ISO8601)。这需要一些技巧......

在 T-SQL SP 中试试这个:

DECLARE @xml XML=
'<recording>
    <dataformat>audio</dataformat>
    <starttime>2015-02-09 08:57:08:000 +0200</starttime>
    <endtime>2015-02-09 08:58:48:000 +0200</endtime>
    <nostart>false</nostart>
    <noend>false</noend>
    <recordingtype>stnbulk</recordingtype>
    <recordingline></recordingline>
    <servicename>005379763634</servicename>
    <servicenumber></servicenumber>
    <deliberatebreak>0</deliberatebreak>
    <calldirection>Outgoing</calldirection>
    <filename>890001000000003.wav</filename>
    <otherinum>0</otherinum>
    <callparty>1</callparty>
    <recordingowners>
        <recordingowner>131</recordingowner>
    </recordingowners>
    <parties>
        <party id="1">
            <number>131</number>
            <name>Santral131</name>
            <pstarttime>2015-02-09 08:58:48:912 +0200</pstarttime>
            <pendtime>2015-02-09 08:58:48:912 +0200</pendtime>
        </party>
        <party id="2">
            <number>005379763634</number>
            <pstarttime>2015-02-09 08:58:48:912 +0200</pstarttime>
            <pendtime>2015-02-09 08:58:48:912 +0200</pendtime>
        </party>
    </parties>
    <guids>
    </guids>
</recording>';

--这是实际的查询

--INSERT INTO YourTargetTable(col1,col2,col3...)
SELECT r.value('(dataformat/text())[1]','nvarchar(max)') AS dataformat
      ,CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(r.value('(starttime/text())[1]','nvarchar(max)'),11,1,'T'),20,1,'.'),24,1,''),27,0,':'),127) AS starttime
      ,r.value('(nostart/text())[1]','bit') AS nostart
      --more columns
      ,r.value('(recordingowners/recordingowner/text())[1]','bit') AS recordingowner --if there might be more than one, this would need one more call to .nodes()
      ,p.value('@id','int') AS party_id
      ,p.value('(number/text())[1]','nvarchar(max)') AS party_number
      --more columns
FROM @xml.nodes('/recording') AS A(r)
OUTER APPLY A.r.nodes('parties/party') AS B(p)

(部分)结果

audio   2015-02-09 08:57:08.0000000 +02:00  0   1   1   131
audio   2015-02-09 08:57:08.0000000 +02:00  0   1   2   005379763634

提示:如果您不需要时区,您可以使用此技巧将时区隐式添加到日期时间...

DECLARE @dtZ DATETIMEOFFSET=CONVERT(DATETIMEOFFSET,'2015-02-09T08:58:48.912+02:00',127);
SELECT (SELECT @dtZ FOR XML PATH(''),TYPE).value('.','datetime');

结果现在已经到了6 的小时...

2015-02-09 06:58:48.913

一些背景:ISO8601 格式看起来像这样

2015-02-09T08:58:48.9120000+02:00

如果 XML 中的字符串格式正确,则读取与任何其他值一样容易。我的代码使用多个 STUFF() 调用来更正格式以使其可转换...

【讨论】:

  • 感谢您的支持。这对我的问题非常有用。
猜你喜欢
  • 2011-09-06
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
相关资源
最近更新 更多