【问题标题】:Flat file destination columns data types validation平面文件目标列数据类型验证
【发布时间】:2019-03-01 19:56:26
【问题描述】:

通过 OLE DB 源读取 INT 类型的源数据库字段。它最终被写入平面文件目标。目标平面文件连接管理器 > 高级页面将其报告为 four-byte signed integer [DT_I4]

这种数据类型让我觉得它表示二进制。显然,事实并非如此。我很惊讶它不是更通用的numeric [DT_NUMERIC]

我将此类型设置更改为single-byte signed integer [DT_I1]。我预计这会失败,但事实并非如此。该过程产生了相同的结果,即使该字段的值始终 > 127。为什么这没有失败?

产生的一些值是

1679576722
1588667638
1588667638
1497758544
1306849450
1215930367
1215930367
1023011178
1932102084 

显然,超出了single-byte signed integer [DT_I1] 的范围。

作为一个相关问题,是否可以将二进制数据输出到平面文件?如果是这样,应该使用什么设置以及在哪里使用?

【问题讨论】:

  • 文件里放的是什么数字?是 >127 的数字还是溢出?

标签: csv ssis integer flat-file ssis-data-types


【解决方案1】:

数据类型验证

我认为这个问题与使用的连接管理器有关,因为数据类型验证(管道外部)不是由集成服务完成的,而是由服务提供商完成的:

  • 用于 Excel 和 Access 的 OLEDB
  • 用于 SQL Server 的 SQL 数据库引擎
  • ...

对于平面文件连接管理器,它不保证任何数据类型的一致性,因为所有值都存储为文本。例如尝试添加一个平面文件连接管理器并选择一个包含名称的文本文件,尝试将列数据类型更改为日期并转到列预览选项卡,它将显示所有列而没有任何问题。它只处理用于从平面文件读取的行分隔符、列分隔符、文本限定符和常用属性。 (类似于 VB.NET 中的 TextFieldParser 类)

数据类型可能导致异常的唯一情况是当您使用平面文件源时,因为平面文件源将在平面文件连接管理器和链接中创建具有定义元数据的外部列当 SSIS 尝试从平面文件源读取时,外部列将抛出异常

二进制输出

您应该在包中将该列转换为二进制并将其映射到目标列。例如,您可以使用脚本组件来执行此操作:

public override void myInput_ProcessInputRow(myInputBuffer Row)
  {

  Row.ByteValues=System.Text.Encoding.UTF8.GetBytes (Row.name);

  }

我没有尝试这是否适用于派生列或数据转换转换。

参考文献

【讨论】:

    【解决方案2】:

    在重新阅读问题以确保它与我的校对编辑相符后,我意识到我似乎没有回答您的问题 - 对此感到抱歉。我留下了第一个答案,以防万一。

    SSIS 似乎没有强制执行目标元数据;但是,它将强制执行源元数据。我创建了一个范围为 -127 到 400 的测试文件。我使用以下场景对此进行了测试:

    • 测试 1: 具有带符号 1 字节数据类型的源和目标平面文件连接管理器。
    • 结果 1: 失败
    • 测试 2: 源是 4 字节有符号的,目标是 1 字节有符号的。
    • 结果 2:通过

    SSIS 的管道元数据验证只关心与管道宽度匹配的输入元数据。它似乎并不关心输出是什么。不过,它使您能够将目标设置为任何下游源,以便它可以检查目标(即 SQL Server)元数据是否匹配并提供警告。

    这是一个出乎意料的结果——我预计它会像你一样失败。直观地说,它没有失败的事实仍然是有道理的。由于我们正在写入 CSV 文件,因此无法控制所需的元数据是什么。但是,如果我们将其连接到 SQL Server 目标并且元数据不匹配,那么 SQL Server 将对超出范围的数据皱眉(请参阅我的其他答案)。

    现在,我仍然会设置输出的元数据以匹配它在管道中的内容,因为这对于区分字符串和数字数据类型有重要的考虑。因此,如果您尝试将日期时间设置为整数,那么将没有文本限定符,这可能会导致下一个输入过程出错。相反,您可能会遇到将整数设置为 varchar 并具有相同的问题,这意味着它将获得一个文本限定符。

    我认为没有强制执行目标元数据这一事实是 SSIS 中的一个薄弱环节。但是,可以通过将其设置为匹配管道缓冲区来取消它,假设它是设计中的最后一个任务,它会自动完成。话虽如此,如果您在开发完成后更新管道上的元数据,那么您将真正享受在整个管道中更新元数据,因为某些任务必须打开和关闭,而其他任务必须删除和重新创建以更新元数据。

    其他信息

    TL DR: TinyInt 在 SQL Server 中存储为无符号数据类型,这意味着它支持 0 到 255 之间的值。因此,可以接受大于 127 的值 - 最高为 255。将导致错误。

    字节大小表示可能组合的最大数量,其中有符号/无符号表示范围是否分为正值和负值。

    • 1 字节 = SQL Server 中的 TinyInt
    • 1 字节为 8 位 = 256 种组合
    • 有符号范围:-128 到 127
    • 无符号范围:0 到 255

    请务必注意,SQL Server 支持直接对数据类型进行签名。我的意思是没有办法将整数数据类型(即 TinyInt、Int 和 BigInt)设置为有符号或无符号。

    • TinyInt 它是无符号
    • Int 和 BigInt 已签名

    请参阅下面的参考:SQL Server 自动标识字段的最大大小

    如果我们尝试将 TinyInt 设置为无符号范围之外的任何值(例如,-1 或 256),则会收到以下错误消息:

    这就是为什么你可以设置一个大于 127 的值。

    内部错误消息:

    BigInt 错误消息:

    关于 Identity 列,如果我们将 Identity 列声明为 Int(即 32 位 ~= 43 亿个组合)并将种子设置为 0,增量为 1,那么 SQL Server 之前只会转到 2,147,483,647 行它停止,这是最大的有符号值。但是,我们少了一半的范围。如果我们将种子设置为 -2,147,483,648(不要忘记在范围内包含 0),那么 SQL Server 将在停止之前递增整个组合范围。

    参考资料:

    SSIS Data Types and Limitations

    Max Size of SQL Server Auto-Identity Field

    【讨论】:

    • 我会给你复选标记,但解释似乎是微软不尊重输出类型设置,如果它可以逃脱它。
    • @lit 谢谢。关于二进制数据类型,试试 DT_BYTE。对于 SQL Server,将其映射到 VARBINARY。结果值为十六进制,因为通过 SqlBinary 结构从 SSIS 到 SQL Server 进行了隐式转换。 docs.microsoft.com/en-us/dotnet/api/…这应该是一个单独的问题。
    • @JWeezy 我认为您应该删除另一个答案并将其写在此答案中的 其他信息部分下
    • @JWeezy - 您是否拥有或知道必须删除和重新创建的组件列表?
    • @lit Merge Join 我知道肯定是一个,我认为如果管道的现有列元数据发生变化,也必须替换 Sort 和 Union All。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 2018-02-19
    • 2012-02-03
    相关资源
    最近更新 更多