我已经使用 BIDS Helper 1.6.6.0 在 BIDS 2008 上成功创建了一个 BIML 脚本,该脚本自动创建 SSIS 包以将数据从 Oracle 数据库(11g 企业版版本 11.2.0.3.0 - 64 位)导入 SQL Server 2008 R2。我在包运行时遇到问题,导致包在数据流验证时失败:
警告:组件“源”(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 提供程序无法在类型“DT_BYTES”和“GROSS_BASE_AMOUNT”的“DT_NUMERIC”之间转换。
错误:任务验证期间出现错误。
NUMBER
经过检查, Oracle 中没有比例和精度的列的元数据似乎映射到DT_BYTES
生成的 SSIS。上述对象(一个视图)在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 和 NULLDATA_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 文档指出,这相当于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>
提前致谢。