【发布时间】:2019-02-07 14:42:44
【问题描述】:
我有一个 Oracle 数据库,其中包含一些我想要移动到 SQL Server 的数据。
问题是我的 Oracle DB 有一些类型为 TIMESTAMP(0) WITH TIME ZONE 的列,而 SSIS 将 thous 检测为 CLOB。所以它不能说它不能将CLOB 转换为datetime2。
我已经在 SQL Server 数据库中创建了表。所以它只是通过一些类型转换来移动数据。
我正在使用 SQL Server Management Studio (SSMS) 中的 SQL Server 导入和导出向导 (SSIS)。
我使用 .NET Framework Data Provider for Oracle 连接到 Oracle DB,使用 SQL Server Native Client 11.0 连接到我的 SQL Server。
我的源类型是TIMESTAMP(0) WITH TIME ZONE,我的目标类型是datetime2。
这是我得到的错误:
[Source Information]
Source Location : localhost
Table: "MYSPACE"."MYTABLE"
Column: START_DATE
Column Type: CLOB
SSIS Type: Unicode text stream [DT_NTEXT]
Mapping file (to SSIS type): C:\Program Files (x86)\Microsoft SQL Server\140\DTS\MappingFiles\OracleClientToSSIS10.XML
[Destination Information]
Destination Location : localhost
Destination Provider : SQLNCLI11
Table: [dbo].[mytable]
Column: start_date
Column Type: datetime2
SSIS Type: database timestamp with precision [DT_DBTIMESTAMP2]
Mapping file (to SSIS type): C:\Program Files (x86)\Microsoft SQL Server\140\DTS\MappingFiles\MSSQLToSSIS10.XML
[Conversion Steps]
Conversion unknown ...
SSIS conversion file: C:\Program Files (x86)\Microsoft SQL Server\140\DTS\binn\DtwTypeConversion.xml
如您所见,START_DATE 列被检测为 CLOB。这是不正确的。
我查看了 OracleClientToSSIS10.XML 的内部
<!-- TIMESTAMP 10.* -->
<dtm:DataTypeMapping >
<dtm:SourceDataType>
<dtm:DataTypeName>timestamp</dtm:DataTypeName>
</dtm:SourceDataType>
<dtm:DestinationDataType>
<dtm:NumericType>
<dtm:DataTypeName>DT_DBTIMESTAMP2</dtm:DataTypeName>
<dtm:SkipPrecision/>
<dtm:UseSourceScale/>
</dtm:NumericType>
</dtm:DestinationDataType>
</dtm:DataTypeMapping>
<!-- TIMESTAMP WITH TIME ZONE 10.* -->
<dtm:DataTypeMapping >
<dtm:SourceDataType>
<dtm:DataTypeName>TIMESTAMP WITH TIME ZONE</dtm:DataTypeName>
</dtm:SourceDataType>
<dtm:DestinationDataType>
<dtm:NumericType>
<dtm:DataTypeName>DT_DBTIMESTAMPOFFSET</dtm:DataTypeName>
<dtm:SkipPrecision/>
<dtm:UseSourceScale/>
</dtm:NumericType>
</dtm:DestinationDataType>
</dtm:DataTypeMapping>
<!-- CLOB -->
<dtm:DataTypeMapping >
<dtm:SourceDataType>
<dtm:DataTypeName>CLOB</dtm:DataTypeName>
</dtm:SourceDataType>
<dtm:DestinationDataType>
<dtm:CharacterStringType>
<dtm:DataTypeName>DT_NTEXT</dtm:DataTypeName>
<dtm:Length>255</dtm:Length>
</dtm:CharacterStringType>
</dtm:DestinationDataType>
</dtm:DataTypeMapping>
看起来不错吧?
【问题讨论】:
-
不是 Oracle 人员,但他们的日期/时间表示与 SQL Server 之间的差异是/曾经是已知的不兼容。在没有看到数据实际外观的示例的情况下,我会假设源值中有实际的偏移值
-05:00,它不会映射到 datetime2。我会做相当于将 Oracle 中的日期转换为格式为yyyy-mm-ddThh:mm:ss.ms的字符字段,并让 Oracle 也处理时区。否则,您需要将 SQL Server 中的目标类型更改为datetimeoffset,然后在 SSIS 的字符串中包含偏移信息 -
出于测试目的,我添加了一个带有 NULL 值的
TIMESTAMP(无时区)列,并尝试将其映射到 MSSQL 中的datetime2列。它仍被检测为CLOB列。所以认为实际值在这个阶段是无关紧要的。 -
框架随附的适用于 Oracle 的 .NET 框架提供程序已过时且不受支持 - 自首次包含以来,它基本上没有更新。使用 Oracle 自己的提供程序。如果所有其他方法都失败了,一个相当简单的解决方法是首先通过查询或视图将 Oracle 中的数据类型转换为任何有效的数据类型(如果您使用
DATETIME2作为目标而不是DATETIMEOFFSET你大概不对于初学者来说,不需要时区信息,所以 Oracle 端的普通TIMESTAMP也应该这样做)。 -
解决此问题的第一步是让 SSIS 不将您的传入列检测为 CLOB/DT_NTEXT。这就是为什么我指出您应该使用 Oracle 等效项将日期时间转换为 ISO 格式的字符串。然后,SSIS 引擎将检测到 DT_STR/DT_WSTR,然后将您的数据推送到目标的提供程序应该具有转换为目标格式的智能。
-
它应该显示为
Microsoft OLE DB Provider for Oracle。我还验证了我可以在导入/导出向导中使用它。
标签: sql-server oracle ssis ssms