2017-08-29 4 views
0

Je suis assez nouveau à BIML et je suis assez bloqué avec un problème, pour lequel je ne pouvais pas trouver une solution appropriée ici ou dans un autre forum. La tâche à accomplir est de créer des paquets SSIS ETL pour quelque chose comme 60 tables afin de charger des données du serveur A vers le serveur B. Comme je ne pensais pas créer les paquets manuellement, j'ai décidé de donner BIML un essai. Cependant, JE OBTENE les paquets désirés (un par table), MAIS chaque paquet lance un "Les métadonnées de la colonne de sortie suivante ne correspondent pas aux métadonnées des colonnes externes auxquelles les colonnes de sortie sont associées" dans la source de la flux de données et avec cela une erreur/avertissement dans la destination ainsi. La colonne qui jette l'erreur (ou au moins une colonne ...) est de type DataType [image] (je n'ai pas d'influence sur ce type de données - c'est comme cela est fourni par le système source). Cependant, OutputColumn que génère BIML reçoit le type de données DT_NTEXT, qui bien sûr ne correspond pas au type de la colonne externe (image).SQL Server ETL via BIML

Après ce que je suis arrivé à ce jour:

<#@ template language="C#" hostspecific="true"#> 
<#@ import namespace="System.Data" #> 

<Biml xmlns="http://schemas.varigence.com/biml.xsd"> 
    <Connections> 
     <OleDbConnection Name="Source" ConnectionString="#####"/> 
     <OleDbConnection Name="Target" ConnectionString="#####"/> 
    </Connections> 
    <Packages> 
     <# 
      string metadataConnectionString = "#####"; 
      DataTable tables = ExternalDataAccess.GetDataTable(metadataConnectionString, 
      "SELECT s.name + '_' + t.name AS Bez, '[' + s.name + '].[' + t.name + ']' AS Col FROM sys.tables t INNER JOIN sys.schemas s on t.schema_id = s.schema_id"); 
      foreach (DataRow row in tables.Rows) 
      { 
      #> 
       <Package Name="Extract_<#=row[0]#>" ConstraintMode="Parallel" AutoCreateConfigurationsType="None"> 
        <Tasks> 
         <ExecuteSQL Name="Truncate <#=row[0]#>" ConnectionName="Target"> 
          <DirectInput> 
           Truncate Table <#=row[1]#> 
          </DirectInput> 
         </ExecuteSQL> 

         <Dataflow Name="Copy Data"> 
          <PrecedenceConstraints> 
           <Inputs> 
            <Input OutputPathName="Truncate <#=row[0]#>.Output" /> 
           </Inputs> 
          </PrecedenceConstraints> 
          <Transformations> 
            <OleDbSource Name="Retrieve Data" ConnectionName="Source"> 
             <ExternalTableInput Table="<#=row[1]#>" /> 
            </OleDbSource> 
            <OleDbDestination Name="Insert Data" ConnectionName="Target"> 
             <ExternalTableOutput Table="<#=row[1]#>"/> 
            </OleDbDestination> 
           </Transformations> 
          </Dataflow> 
        </Tasks> 
       </Package> 
      <# 
      } 
     #> 
    </Packages> 
</Biml> 

Depuis que je lis qu'il pourrait être relié au fournisseur utilisé dans les connexions: J'utilise Provider = SQLNCLI11.1 avec Integrated Security = SSPI

Toute aide serait grandement appréciée. Merci!

+0

Apparemment la problème peut être bypas sed en définissant ValidateExternalMetadata à false - de toute façon il serait bon de connaître la raison de cette erreur ... – Tyron78

+0

Source et destination sont tous deux SQL Server? De même, chaque paquet devrait-il utiliser 'dbo.DWH_SalesHeader' comme source? – billinkc

+0

Non, la source varie aussi - je viens de modifier le code – Tyron78

Répondre

1

C'est parce que BIML et SSIS utilise son propre type de données. Voir ce lien pour Datatypes correct:

https://www.cathrinewilhelmsen.net/2014/05/27/sql-server-ssis-and-biml-data-types/

Vous pouvez mettre dans votre code dans un extrait et l'appeler. Correctement, vous devez également modifier votre source de ExternalTableInput pour l'entrée directe, de sorte que vous écrivez votre sélection SQL automatiquement. C'est un vieux code - C'est beaucoup plus facile à mettre dans une DLL Libaray.

Ce que je l'ai fait est comme ceci:

<Packages> 
<# foreach (DataRow dr in dt.Rows) { 
PackageName = "EXTRACT_SQL_"+dr["S_EntityName"].ToString().Replace(".","_").ToUpper(); #> 
<Package Name="<#=PackageName #>" ConstraintMode="Linear"> 
    <#=CallBimlScript("..\\..\\..\\Log\\StaticVariables.biml", "Log") #> 
    <Tasks> 
     <Container Name="SEQ Load arc <#=dr["D_EntityName"] #>" ConstraintMode="Linear"> 
      <Tasks> 
       <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogStart.biml", PackageName) #> 
       <ExecuteSQL Name="SQL TRUNCATE TABLE <#=dr["D_EntityName"] #>" ConnectionName="<#=dr["D_DatabaseName"] #>" ResultSet="None"> 
        <DirectInput> 
         TRUNCATE TABLE [<#=dr["D_SchemaTypeName"]#>].[<#=dr["D_EntityName"] #>] 
        </DirectInput> 
       </ExecuteSQL> 
       <Dataflow Name="DFT_SourceToExtract_<#=dr["D_EntityName"] #>"> 
        <Transformations> 
         <OleDbSource Name="OLDB SRC_<#=dr["S_DatabaseName"]#>_<#=dr["S_EntityName"] #>" ConnectionName="<#=dr["S_DatabaseName"]#>"> 
          <DirectInput><# DataTable ColumnMetaData = ExternalDataAccess.GetDataTable(metadataConnectionString, @" 
           SELECT DISTINCT [S_ColumnName] 
           FROM [model].[vRelationDatabaseSchemaEntityColumn] 
           WHERE [S_SystemTypeName] = 'SQL Server' AND S_EntityID = "+dr["S_EntityID"]+""); 
           string columns = String.Join(String.Format(", {0}", System.Environment.NewLine), ColumnMetaData.Rows.Cast<DataRow>().Select(r => "["+r["S_ColumnName"]+"]").ToArray()); #> 
           SELECT 
           <#=columns #> 
           FROM [<#=dr["S_SchemaTypeName"] #>].[<#=dr["S_EntityName"] #>] WITH (NOLOCK) 
          </DirectInput> 
         </OleDbSource> 
         <DerivedColumns Name="DRV Konverter datatyper"> 
          <InputPath OutputPathName="OLDB SRC_<#=dr["S_DatabaseName"]#>_<#=dr["S_EntityName"] #>.Output" /> 
           <#=CallBimlScript("..\\DerivedColumnDatatypeConversion.biml",dr["S_EntityID"]) #> 
         </DerivedColumns> 
         <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogDataFlowDerivedColumns.biml") #> 
         <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogDataFlowRowCount.biml") #> 
         <OleDbDestination Name="OLDB DEST_<#=dr["D_DatabaseName"] #>_<#=dr["D_EntityName"] #>" ConnectionName="<#=dr["D_DatabaseName"] #>"> 
          <ExternalTableOutput Table="[<#=dr["D_SchemaTypeName"] #>].[<#=dr["D_EntityName"] #>]" /> 
           <#=CallBimlScript("..\\OleDbDestinationColumnMapping.biml", dr["S_EntityID"]) #> 
         </OleDbDestination> 
        </Transformations> 
       </Dataflow> 
       <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogEnd.biml") #> 
      </Tasks> 
     </Container> 
    </Tasks> 
</Package> 
<#} #> 
<Package Name="<#=MasterPackageName#>" ConstraintMode="Linear" ProtectionLevel="DontSaveSensitive"> 
    <#=CallBimlScript("..\\..\\..\\Log\\StaticVariables.biml", "Log") #> 
    <Tasks> 
     <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogStart.biml", MasterPackageName) #> 
     <Container Name="SEQ Run packages in parallel" ConstraintMode="Parallel"> 
      <Tasks>  
      <# foreach (string package in packagescreated) { #> 
       <ExecutePackage Name="EPT_<#=package#>"> 
        <ExternalProjectPackage Package="<#=package#>.dtsx" ></ExternalProjectPackage> 
       </ExecutePackage> 
      <# } #> 
      </Tasks> 
     </Container> 
     <#=CallBimlScript("..\\..\\..\\Log\\ETL_ExecutionLogEnd.biml") #> 
    </Tasks> 
</Package> 

Comme vous pouvez le voir j'appelle DerivedColumnDatatypeConversion qui ressemble à ceci:

<#@ import namespace="System.Data" #> 
<#@ include file="..\\..\\Connections\\LocalConnection.biml" #> 
<#@ include file="..\..\Utility\i-GetSqlToBimlDatatype.biml" #> 
<#@ property name="pEntityID" type="Int32" #> 
<# 
int EntityID = pEntityID; 
bool isLenghtInt = false; 
int intLenght; 

var metadataSelect = @" 
SELECT [S_ColumnName] 
    ,[S_Datatype] 
    ,[D_ColumnName] 
    ,[D_Datatype] 
    ,[D_Length] 
    ,[D_Precision] 
    ,[D_Scale] 
    ,[Conversion] 
    ,[S_SystemTypeName] 
    ,[FlatFileType] as [S_FlatFileType] 
FROM [model].[vRelationDatabaseSchemaEntityColumn] v 
left join [model].[SourceFile] s on s.[FK_Entity]=v.[S_EntityID] 
WHERE [S_EntityID] = " + EntityID + ""; 

DataTable dt = ExternalDataAccess.GetDataTable(metadataConnectionString, 
metadataSelect); 
#> 
<Columns> 
<Column Name="DummyIfEmpty" DataType="Int32">1</Column> 
<# foreach (DataRow dr in dt.Rows) { 
isLenghtInt = Int32.TryParse(dr["D_Length"].ToString(),out intLenght); 

    if (dr["Conversion"].ToString() == "Convert_Date") 
    { 
     if(dr["S_Datatype"].ToString().ToLower() == "datetime" || dr["S_Datatype"].ToString().ToLower() == "datetime2" || dr["S_Datatype"].ToString().ToLower() == "date") 
     { 
      if(dr["S_SystemTypeName"].ToString().ToLower() == "db2" || dr["S_FlatFileType"].ToString().ToLower() == "Fixed Width"){ 
       //Fjern kommenteringen på denne for at genaktivere datatypekonvertering på DB2 
       //WriteLine('<Column Name=\"' + dr["S_ColumnName"] + '_Converted' + '\" ' + GetSqlToBimlDatatype(dr["D_DataType"].ToString()) +'>(DT_DBDATE)(SUBSTRING(['+dr["S_ColumnName"]+'],7,4)+"-"+SUBSTRING(['+dr["S_ColumnName"]+'],4,2)+"-"+SUBSTRING(['+dr["S_ColumnName"]+'],1,2))</Column>'); 
      } else { 
       WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" " + GetSqlToBimlDatatype(dr["D_DataType"].ToString()) +">(DT_DBDATE)["+dr["S_ColumnName"]+"]</Column>"); 
      } 
     } 
     else 
     { 
      WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" " + GetSqlToBimlDatatype(dr["D_DataType"].ToString()) +">DATEADD(\"d\",(DT_I8)[" + dr["S_ColumnName"] + "],(DT_DBDATE)\"1960-01-01\")</Column>"); 
     } 
    } 


if(dr["S_Datatype"].ToString().ToLower() == "varchar" || dr["S_Datatype"].ToString().ToLower() == "text") { 

    if(dr["D_Length"].ToString().ToLower() == "max" || (intLenght > 4000 && isLenghtInt == true)) { //Hvis varchar er max eller over 4000 så konverter til nvarchar(4000) 

    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+GetSqlToBimlDatatype("nvarcharmax") +">(DT_WSTR,4000)["+dr["S_ColumnName"]+"]</Column>"); 

    } 
    else 
    { 
    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+GetSqlToBimlDatatype(dr["D_DataType"].ToString(),dr["D_Length"].ToString()) +">(DT_WSTR,"+dr["D_Length"]+")["+dr["S_ColumnName"]+"]</Column>"); 
} 
} 


    if(dr["S_Datatype"].ToString().ToLower() == "char") 
    { 
     if(dr["D_Length"].ToString().ToLower() == "max") 
     { 
      WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+GetSqlToBimlDatatype("charmax") +">(DT_WSTR,4000)["+dr["S_ColumnName"]+"]</Column>"); 
} 
else 
{ 
      WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+GetSqlToBimlDatatype(dr["D_DataType"].ToString(),dr["D_Length"].ToString()) +">(DT_WSTR,"+dr["D_Length"]+")["+dr["S_ColumnName"]+"]</Column>"); 

} 
     } 
    if (dr["Conversion"].ToString() == "Convert_Datetime") 
{ 
    if(dr["S_Datatype"].ToString().ToLower() =="datetime") 
    { 
WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+ 
GetSqlToBimlDatatype(dr["D_DataType"].ToString()) + ">(DT_DBTIMESTAMP)[" + 
dr["S_ColumnName"] + "]</Column>"); 

} 
else 
{ 
    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+ GetSqlToBimlDatatype(dr["D_DataType"].ToString()) + ">([" + dr["S_ColumnName"] + "] > 2147483647) ? DATEADD(\"Hh\",(DT_I8)[" + dr["S_ColumnName"] + "]/3600,(DT_DBTIMESTAMP)\"1960-01-01\") : DATEADD(\"s\",(DT_I8)[" + dr["S_ColumnName"] + "],(DT_DBTIMESTAMP)\"1960-01-01\")</Column>"); 
} 
} 

    if (dr["Conversion"].ToString() == "Convert_Int") 
    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" "+ 
GetSqlToBimlDatatype(dr["D_DataType"].ToString()) + ">(DT_I4)ROUND([" + 
dr["S_ColumnName"] + "],0)</Column>"); 
if (dr["Conversion"].ToString() == "Convert_Bigint") 
    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" " 
+ GetSqlToBimlDatatype(dr["D_DataType"].ToString())+">(DT_I8)ROUND([" + 
dr["S_ColumnName"] + "],0)</Column>"); 
if (dr["Conversion"].ToString() == "Convert_Decimal") 
    WriteLine("<Column Name=\"" + dr["S_ColumnName"] + "_Converted" + "\" " + GetSqlToBimlDatatype(dr["D_DataType"].ToString(), null, dr["D_Precision"].ToString(), dr["D_Scale"].ToString()) + ">(DT_NUMERIC," + dr["D_Precision"] + "," + dr["D_Scale"] + ")[" + dr["S_ColumnName"] + "]</Column>"); 

}#> 

<#+ 
private string GetSqlToBimlDatatype(string datatype, string length = null, string precision = null, string scale = null) 
    { 
     string bimlDatatype = "DataType=\"AnsiString\" Length=\"50\" CodePage=\"1252\""; 
     switch (datatype) 
     { 
      case "uniqueidentifier": 
       bimlDatatype = "DataType=\"Guid\" Length=\"12\""; 
       break; 
       // Dates 
      case "image": 
       bimlDatatype = "DataType=\"Binary\""; 
       break; 
      case "date": 
       bimlDatatype = "DataType=\"Date\" "; 
       break; 
      case "time": 
       bimlDatatype = "DataType=\"Time\""; 
       break; 
      case "smalldatetime": 
       bimlDatatype = "DataType=\"DateTime\""; 
       break; 
      case "datetime": 
       bimlDatatype = "DataType=\"DateTime\""; 
       break; 
      case "datetime2": 
       bimlDatatype = "DataType=\"DateTime2\""; 
       break; 
      case "datetimeoffset": 
       bimlDatatype = "DataType=\"DateTimeOffset\""; 
       break; 
       // Intigers 
      case "tinyint": 
       bimlDatatype = "DataType=\"SByte\""; 
       break; 
      case "smallint": 
       bimlDatatype = "DataType=\"Int16\""; 
       break; 
      case "int": 
       bimlDatatype = "DataType=\"Int32\""; 
       break; 
      case "bigint": 
       bimlDatatype = "DataType=\"Int64\""; 
       break; 
       // Numerics 
      case "real": 
       bimlDatatype = "DataType=\"Single\""; 
       break; 
      case "money": 
       bimlDatatype = "DataType=\"Currency\""; 
       break; 
      case "float": 
       bimlDatatype = "DataType=\"Double\""; 
       break; 
      case "numeric": 
       bimlDatatype = "DataType=\"Decimal\" Precision=\"" + precision + "\" Scale=\"" + scale + "\""; 
       break; 
      case "smallmoney": 
       bimlDatatype = "DataType=\"Currency\""; 
       break; 
      case "decimal": 
       bimlDatatype = "DataType=\"Decimal\" Precision=\"" + precision + "\" Scale=\"" + scale + "\""; 
       break; 
      case "timestamp": 
       bimlDatatype = "DataType=\"Binary\""; 
       break; 
      case "bit": 
       bimlDatatype = "DataType=\"Boolean\""; 
       break; 
      case "hierarchyid": 
       bimlDatatype = "DataType=\"String\" Length=\"36\""; 
       break; 
       // Strings 
      case "varchar": 
       bimlDatatype = "DataType=\"AnsiString\" Length=\"" + length + "\""; 
       break; 
      case "char": 
       bimlDatatype = "DataType=\"AnsiStringFixedLength\" Length=\"" + length + "\""; 
       break; 
       case "charmax": 
       bimlDatatype = "DataType=\"String\""; 
       break; 
      case "nvarchar": 
       bimlDatatype = "DataType=\"StringFixedLength\" Length=\"" + length + "\""; 
       break; 
      case "nvarcharmax": 
       bimlDatatype = "DataType=\"String\""; 
       break; 
      case "nchar": 
       bimlDatatype = "DataType=\"StringFixedLength\" Length=\"" + length + "\""; 
       break; 
      case "sysname": 
       bimlDatatype = "DataType=\"String\" Length=\"128\""; 
       break; 
       // Review as these types should not be part of DWH 
      case "sql_variant": 
       bimlDatatype = "DataType=\"Object\""; 
       break; 
      case "text": 
       bimlDatatype = "DataType=\"AnsiString\" Length=\"" + length + "\""; 
       break; 
      case "ntext": 
       bimlDatatype = "DataType=\"String\" Length=\"" + length + "\""; 
       break; 
       // Review as these types should not be part of DWH 
      case "varbinary": 
       bimlDatatype = "DataType=\"Binary\" Length=\"" + length + "\""; 
       break; 
      case "binary": 
       bimlDatatype = "DataType=\"Binary\" Length=\"" + length + "\""; 
       break; 
      case "xml": 
       bimlDatatype = "DataType=\"Xml\""; 
       break; 
      // default: 
      // break; 
     } 
     return bimlDatatype; 
    } 
#>