我已经在BIDS 2008上使用BIDS Helper 1.6.6.0成功创建了一个BIML脚本,该脚本自动创建SSIS包,以便将数据从Oracle数据库(11g企业版11.2.0.3.0 - 64位)导入SQL Server 2008 R2 . 我在包运行时出现问题导致程序包在数据流阈值时失败:
警告:组件“Source”(1)的外部列与数据源列不同步 . 需要更新外部列“LIMIT_AMOUNT” . 需要更新外部列“LIMIT_BASE_AMOUNT” . 需要更新外部列“GROSS_BASE_AMOUNT” . 错误:OLE DB适配器使用的OLE DB提供程序无法在“LIMIT_AMOUNT”类型“DT_BYTES”和“DT_NUMERIC”之间进行转换 . 错误:OLE DB适配器使用的OLE DB提供程序无法在“LIMIT_BASE_AMOUNT”类型“DT_BYTES”和“DT_NUMERIC”之间进行转换 . 错误:OLE DB适配器使用的OLE DB提供程序无法在“GROSS_BASE_AMOUNT”类型“DT_BYTES”和“DT_NUMERIC”之间进行转换 . 错误:任务验证期间出错 .
经过检查,似乎Oracle中没有规模和精度的 NUMBER
列的元数据映射到生成的SSIS中的 DT_BYTES
. Oracle中上述对象(视图)的描述如下:
Name Null Type
--------------------- ---- ------------
ID NUMBER(12)
CURRENCY VARCHAR2(3)
LIMIT_AMOUNT NUMBER
LIMIT_BASE_AMOUNT NUMBER
GROSS_BASE_AMOUNT NUMBER
STATUS VARCHAR2(15)
签入 all_tab_columns
将三个 NUMBER
列显示为 DATA_LENGTH
为22且NULL DATA_PRECISION
和 DATA_SCALE
.
COLUMN_ID COLUMN_NAME DATA_TYPE DATA_LENGTH DATA_PRECISION DATA_SCALE
---------- ---------------------- ------------- ----------- -------------- ----------
1 ID NUMBER 22 12 0
2 CURRENCY VARCHAR2 3
3 LIMIT_AMOUNT NUMBER 22
4 LIMIT_BASE_AMOUNT NUMBER 22
5 GROSS_BASE_AMOUNT NUMBER 22
6 STATUS VARCHAR2 15
Oracle documentation表示这相当于 float
使用以下格式指定浮点数:NUMBER缺少精度和比例指示符指定Oracle编号的最大范围和精度 .
到目前为止,解决方法是实现一个自定义SELECT,它将这些字段转换为所需的类型,但这不是很优雅或可维护 . 我想了解为什么BIML似乎让数据类型映射错误,而SSIS能够确定在创建包之后首次打开包时元数据是错误的 - 我在BIDS中获得一个弹出窗口,说明
以下输出列的元数据与输出列关联的外部列的元数据不匹配:输出“输出”:“LIMIT_AMOUNT”,“LIMIT_BASE_AMOUNT”,“GROSS_EXP_BASE_AMOUNT”是否要替换元数据输出列与外部列的元数据?
编辑:添加有关连接和数据流的相关Biml详细信息
<#
string OraConnectionStr = @"Provider=OraOLEDB.Oracle;Data Source=(In-line TNS);User Id=redacted;Password=redacted;Persist Security Info=True;";
string StagingConnectionStr = "Data Source=SVR;Initial Catalog=DB;Integrated Security=SSPI;Provider=SQLNCLI10;";
#>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Connections>
<Connection Name="<#=StagingConnectionName#>"
ConnectionString="<#=StagingConnectionStr#>" />
<Connection Name="<#=OraConnectionName#>"
ConnectionString="<#=OraConnectionStr#>" />
</Connections>
<Packages>
<!-- Assume object stagingTables is populated and methods have been defined -->
<# foreach (DataRow row in stagingTables.Rows) { #>
<Package Name="<#= GetChildPackageName(row) #>"
ConstraintMode="Linear" AutoCreateConfigurationsType="None">
<Dataflow Name="<#=GetStagingTableDescriptiveName(row)#>" >
<Tasks>
<Transformations>
<OleDbSource Name="Source - <#=GetStagingTableDescriptiveName(row)#>"
ConnectionName="<#=OraConnectionName#>"
AlwaysUseDefaultCodePage="true"
DefaultCodePage="1252">
<DirectInput>SELECT * FROM <#GetOracleObjectName(row)#></DirectInput>
</OleDbSource>
<OleDbDestination Name="Destination - <#=GetStagingTableDescriptiveName(row)#>"
ConnectionName="<#=DataLoadConnectionName#>">
<ExternalTableOutput Table="<#= GetStagingTableObjectName(row) #>" />
</OleDbDestination>
</Transformations>
</Dataflow>
</Tasks>
</Package>
<# } #>
</Packages
</Biml>
提前致谢 .