【问题标题】:SSIS XML Task with Untyped XML具有无类型 XML 的 SSIS XML 任务
【发布时间】:2015-09-02 16:01:28
【问题描述】:

我对将数据从 XML 数据源加载到 SQL Server 中还很陌生,但过去我已经成功地使用了格式正确的 XML 数据源。我有一个 Web 服务,它通过 SSIS 从第三方解决方案中调用以获取数据。该网络服务将数据吐出如下:

<?xml version="1.0" encoding="utf-16"?>
<EpsTableEx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ErrorString />
  <ErrorNum>1</ErrorNum>
  <Data>
    <ArrayOfString>
      <string>ObjectId</string>
      <string>Form_Type</string>
      <string>Owner</string>
      <string>CompletedDate</string>
      <string>Delivered</string>
      <string>Name</string>
      <string>EventID</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183122</string>
      <string>Form1</string>
      <string>91b</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21966</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183152</string>
      <string>Form1</string>
      <string>2879d</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21967</string>
    </ArrayOfString>
  </Data>
</EpsTableEx>

第一个 ArrayOfString 是列标题,而不是每个元素都是列标题。

在另一个具有正确格式的 XML Web 服务的包中,我正在使用 XML 任务编辑器通过 XPATH 操作进入数据级别,这对我来说在这里不起作用。这会导致 ArrayOfString 和 String 被剥离,所有数据都连接在一起。

我试过了:

  1. 将 XPATH 操作更改为 XML 路径的不同级别,但未成功。
  2. 更改 XSD 文件以尝试强制它认为 ArrayOfString 标记中的文本将是要插入到表中的文本,然后稍后对其进行解析,但没有数据通过。
  3. 将 XSD 文件更改为定义字段的 String1、String2 等,希望它将映射到每个项目的通用字符串标签。

我正在使用 SQL Server 2014 和 Data Tools 来构建 SSIS 包。

编辑: 目标是在 SSIS 中提供一个可以每晚运行的解决方案。

编辑2: 数据将被加载到如下表中:

CREATE TABLE [dbo].[FormXML](

[ObjectID] [nvarchar](255) NULL,
[Form_Type] [nvarchar](255) NULL,
[Owner] [nvarchar](255) NULL,
[CompletedDate] [nvarchar](255) NULL,
[Delivered] [nvarchar](255) NULL,
[Name] [nvarchar](255) NULL,
[EventID] [nvarchar](255) NULL,
[ADD_DTTM] [datetime] NULL DEFAULT (getdate()))

我不关心 ErrorString 或 ErrorNum 节点。我调整了建议的 XML 查询以使用执行 SQL 任务将数据插入到表中。

在 SSIS 中放入变量的 XML 是 +400k 个字符。根据这篇文章(http://www.sqlservercentral.com/articles/SQL+Server/97947/),我在网上看到一个字符串变量有 2GB 的限制。我怀疑这是我的问题,如果我可以将 Web 服务中的 XML 加载到 XML 变量而不是字符串变量中,我就不会遇到这个问题。

【问题讨论】:

  • 您可能必须编写自定义 C# 脚本组件源才能正确解析 XML :-(

标签: sql xml ssis


【解决方案1】:

假设这个 XML 带有一个带有数据行的“表”,我建议不要从第一个块中获取列名。它们可能是“硬编码”的:

只需将其粘贴到一个空的 SQL 查询窗口中并执行。根据您的需要调整它...

declare @x XML='<EpsTableEx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ErrorString />
  <ErrorNum>1</ErrorNum>
  <Data>
    <ArrayOfString>
      <string>ObjectId</string>
      <string>Form_Type</string>
      <string>Owner</string>
      <string>CompletedDate</string>
      <string>Delivered</string>
      <string>Name</string>
      <string>EventID</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183122</string>
      <string>Form1</string>
      <string>91b</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21966</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183152</string>
      <string>Form1</string>
      <string>2879d</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21967</string>
    </ArrayOfString>
  </Data>
</EpsTableEx>';

SELECT ArrayOfString.block.value('string[1]','int') AS ObjectId
      ,ArrayOfString.block.value('string[2]','varchar(max)') AS Form_Type
      ,ArrayOfString.block.value('string[3]','varchar(max)') AS [Owner]
      ,ArrayOfString.block.value('string[4]','date') AS CompletedDated
      ,ArrayOfString.block.value('string[5]','date') AS Delivered
      ,ArrayOfString.block.value('string[6]','varchar(max)') AS [Name]
      ,ArrayOfString.block.value('string[7]','int') AS EventID
FROM @x.nodes('/EpsTableEx/Data/ArrayOfString[position()>1]') AS ArrayOfString(block)

【讨论】:

  • 这适用于 SSMS,但不适用于 SSDT。它将完成,但不会插入任何行。然后你去掉了 XML 的第一行。
  • @WyattShipman,我不明白你错过了什么。该 SQL 没有插入任何内容,因为没有 INSERT 语句 :-) 您没有提供足够的信息,您将如何处理:在哪里插入?目标表的结构如何?你打算用 ErrorString 和 ErrorNum 做什么?并且:我没有去掉第一行,SQL Server 不允许您使用 指令设置编码。请回来提供更多问题/信息...
  • 我通过编辑更新了我的帖子。我希望另一种解决方案是尝试将从服务返回的 XML 写入 XML 文件,但是我需要一种方法来删除该编码指令...
  • @WyattShipman,必须有一点,Web 服务会移交 XML。在这个阶段它应该是“完整的”。您处理这些数据的第一阶段在哪里? XML 的结构是否在您的控制之下?您要写入的 SQL 变量是什么类型的?怎么写?
  • 当网络服务“交出数据”时,它看起来就像我的 OP。我无法控制 Web 服务如何“移交数据”,因为它来自第 3 方解决方案。使用 SSIS,我第一次触摸它时分配输出的位置,我可以将其写入文件或将其存储在字符串变量中。据我所知,没有将其存储到 SSIS 中的 XML 变量中的选项,因此我尝试了文件和字符串变量。最后,我想将它加载到 SQL Server 表中。
【解决方案2】:

我使用 2 个不同的变量解决了这个问题。我将 Web 服务的 XML 输出输入到一个字符串变量中,我们称之为String1。然后我创建了另一个变量,称为String2,并创建了一个表达式以将String1 格式化为可用的XML 字符串。

下面的我的表达式替换了 "\n"、"\r" 和 "xmlns=\"http://Eprise\"" 的所有实例,以正确格式化字符串。然后我使用 SUBSTRING 表达式仅在数据标签中获取字符串的移植。 FINDSTRING 位于数据标签开始的位置,LEN 帮助确定字符串的实际长度。

replace(
    replace(
        replace(
            substring(@[User::String1], 
                      FINDSTRING( @[User::String1] , "<Data", 1) , 
                      LEN( 
                        substring(@[User::String1], 
                                  FINDSTRING( @[User::String1] , 
                                            "<Data", 
                                            1),
                                  LEN(@[User::String1])
                                  )
                        ) -13 
                    )
            ,"\n","")
        ,"\r","")
    ," xmlns=\"http://Eprise\"","")

我必须在String1 中填充至少13 个字符的初始值,以便我可以修剪String1 的结尾以删除最后一个结束标记。我还需要初始值来包含文本“String2 最初评估为真。

String2 格式化后,我使用并执行 SQL 任务。我添加了一个参数,使用String2作为NVARCHAR类型的输入方向,名称为0,长度为2147483647,即2gb,SSIS中字符串的最大值。

我将 SQL 查询从 @Shnugo 调整为:

declare @x as xml

set @x=?

insert into Database.dbo.Table ([ObjectID] ,[Form_Type],[Owner],[CompletedDate],[Delivered],[Name],[EventID])

SELECT block.value('string[1]', 'varchar(max)') AS ObjectId
    ,block.value('string[2]', 'varchar(max)') AS Form_Type
    ,block.value('string[3]', 'varchar(max)') AS OWNER
    ,block.value('string[4]', 'varchar(max)') AS CompletedDated
    ,block.value('string[5]', 'varchar(max)') AS Delivered
    ,block.value('string[6]', 'varchar(max)') AS NAME
    ,block.value('string[7]', 'varchar(max)') AS EventID
FROM @x.nodes('/Data/ArrayOfString[position()>1]') AS ArrayOfString(block)

?从参数中提取值,这是我格式化的 XML 字符串,然后使用 XML 查询将数据插入到表中。

【讨论】:

  • 太棒了!最后一件事:您应该将给定的答案标记为已接受(投票计数器下方的检查),以将此问题标记为已解决。如果您以从其他人那里得到的最佳答案来执行此操作(在这种情况下只有我的:-))此人对 15 个声望点感到满意,您也可以标记自己的答案(在这种情况下没有声望点... )。编码愉快!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
相关资源
最近更新 更多