web-dev-qa-db-fra.com

Comment convertir les codes ErrorCode et ErrorColumn dans SSIS en message d'erreur et en nom de colonne?

Je redirige des lignes d'un fichier source simple vers une destination de fichier simple. Les métadonnées par défaut dans les lignes redirigées sont les suivantes:

  • La ligne source du fichier plat d'origine
  • Le code d'erreur
  • Le ErrorColumn

Ce que j'obtiens dans le fichier plat de sortie est la ligne source (Nice) et le code d'erreur (pas Nice, ex. -1071628249) et la colonne d'erreur (pas Nice car il s'agit de l'ID interne de la colonne).

Comment puis-je transformer les lignes pour générer le message d'erreur (par exemple "Les données ont été tronquées.") Et le nom de la colonne tel que défini dans le fichier source source?

En d'autres termes, au lieu de ...,-1071607675,10, j'aimerais voir:

...,The data was truncated,Firstname

ou alternativement (si le précédent n'est pas possible);

...,DTS_E_FLATFILESOURCEADAPTERSTATIC_TRUNCATED,Firstname.

29
Bernhard Hofmann

Une partie de la question (ajout de la description de l'erreur) peut être réalisée avec un composant de script. Ceci est décrit dans Amélioration d'une sortie d'erreur avec le composant de script .

Il semble que le Dougbert blog ait une solution pour ajouter le nom de la colonne, mais c'est loin d'être simple. Je suis étonné que ce soit si difficile à faire dans SSIS; on pourrait penser que c’est un besoin fondamental de connaître le nom de la source et de la colonne.

13
Bernhard Hofmann

Il y a une réponse beaucoup plus simple. Il suffit de rediriger la sortie d'erreur vers un nouveau fichier de destination (CSV ou autre), puis d'activer un DataViewer sur la sortie d'erreur ....

Data Viewer in SSIS

4
kevin plunkett

Pragmatic Works semble avoir un Erreur Description de la sortie Transform qui fait partie de la Community Edition (Free) du produit appelé "Task Factory". 

La sortie d'erreur Description Transform fournit à l'utilisateur une interface utilisateur capable de récupérer des informations précieuses telles que ErrorCode, ErrorColumn, ErrorDescription, ComponentName (qui a généré l'erreur), ColumnName (si connu), ColumnType et ColumnLength. 

Il vous permet également de transmettre toutes les colonnes d’entrée à la sortie d’erreur. Pour être honnête, il est très pratique et m'a permis de gagner du temps pendant le dépannage de mes packages SSIS.

4
Tyler Ryan

Pour ce faire, utilisez un composant de script en tant que transformation. Redirigez la sortie d'erreur vers le composant de script et suivez les étapes pour obtenir ce que vous recherchez.

(1) composant de script ouvert,

Les colonnes d'entrée sélectionnez  

  1. ErrorColumn
  2. Code d'erreur

Entrée et sortie add Colonnes de sortie

  1. Description d'erreur (DT_STRING 500)
  2. ErrorColumnDescription (DT_STRING 100)

(2) Modifier le script

Coller le code suivant 

    using System;
    using System.Data;
    using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
    using Microsoft.SqlServer.Dts.Runtime.Wrapper;
    #endregion

    /// <summary>
    /// This is the class to which to add your code.  Do not change the name, attributes, or parent
    /// of this class.
    /// </summary>
    [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
    public class ScriptMain : UserComponent
    {

        public override void Input0_ProcessInputRow(Input0Buffer Row)
        {
            var component130 = this.ComponentMetaData as IDTSComponentMetaData130;
            if (component130 != null)
            {
                Row.ErrorDescription = component130.GetErrorDescription(Row.ErrorCode);
                Row.ErrorColumnDescription = component130.GetIdentificationStringByID(Row.ErrorColumn);
            }
        }
4
Sathyanath G
    //column error description 
    Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);

    //we are getting column name with some extra information
    String rawColumnName = this.ComponentMetaData.GetIdentificationStringByLineageID(Row.ErrorColumn);

    //extracting positions of brackets 
    int bracketPos = rawColumnName.LastIndexOf('[')+1;
    int lastBracketPos = rawColumnName.LastIndexOf(']');

    //extracting column name from the raw column name
    Row.ErrorColName = rawColumnName.Substring(bracketPos, (lastBracketPos - bracketPos));
2
observer

Voici une solution qui 

  1. Fonctionne au moment de l'exécution du paquet (non pré-rempli) 
  2. Est automatisé via une tâche de script et un composant
  3. N'implique pas l'installation de nouveaux assemblys ou de composants personnalisés
  4. Est bien compatible BIML

Découvrez la solution complète ici.


Voici la version courte.

  1. Créer 2 variables d'objet, execsObj et lineageIds
  2. Créer une tâche de script dans le flux de contrôle, donnez-lui un accès en lecture/écriture aux deux variables
  3. Insérez le code suivant dans votre tâche de script 
Dictionary<int, string> lineageIds = null;

public void Main()
{
    // Grab the executables so we have to something to iterate over, and initialize our lineageIDs list
    // Why the executables?  Well, SSIS won't let us store a reference to the Package itself...
    Dts.Variables["User::execsObj"].Value = ((Package)Dts.Variables["User::execsObj"].Parent).Executables;
    Dts.Variables["User::lineageIds"].Value = new Dictionary<int, string>();
    lineageIds = (Dictionary<int, string>)Dts.Variables["User::lineageIds"].Value;
    Executables execs = (Executables)Dts.Variables["User::execsObj"].Value;

    ReadExecutables(execs);

    Dts.TaskResult = (int)ScriptResults.Success;
}

private void ReadExecutables(Executables executables)
{
    foreach (Executable pkgExecutable in executables)
    {
        if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.TaskHost)))
        {
            TaskHost pkgExecTaskHost = (TaskHost)pkgExecutable;
            if (pkgExecTaskHost.CreationName.StartsWith("SSIS.Pipeline"))
            {
                ProcessDataFlowTask(pkgExecTaskHost);
            }
        }
        else if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.ForEachLoop)))
        {
            // Recurse into FELCs
            ReadExecutables(((ForEachLoop)pkgExecutable).Executables);
        }
    }
}

private void ProcessDataFlowTask(TaskHost currentDataFlowTask)
{
    MainPipe currentDataFlow = (MainPipe)currentDataFlowTask.InnerObject;
    foreach (IDTSComponentMetaData100 currentComponent in currentDataFlow.ComponentMetaDataCollection)
    {
        // Get the inputs in the component.
        foreach (IDTSInput100 currentInput in currentComponent.InputCollection)
            foreach (IDTSInputColumn100 currentInputColumn in currentInput.InputColumnCollection)
                lineageIds.Add(currentInputColumn.ID, currentInputColumn.Name);

        // Get the outputs in the component.
        foreach (IDTSOutput100 currentOutput in currentComponent.OutputCollection)
            foreach (IDTSOutputColumn100 currentoutputColumn in currentOutput.OutputColumnCollection)
                lineageIds.Add(currentoutputColumn.ID, currentoutputColumn.Name);
    }
}

4. Créez un composant de script dans le flux de données avec un accès en lecture seule à lineageIds et le code suivant.

public override void Input0_ProcessInputRow(Input0Buffer Row)
  {
      Dictionary<int, string> lineageIds = (Dictionary<int, string>)Variables.lineageIds;

      int? colNum = Row.ErrorColumn;
      if (colNum.HasValue && (lineageIds != null))
      {
          if (lineageIds.ContainsKey(colNum.Value))
              Row.ErrorColumnName = lineageIds[colNum.Value];

          else
              Row.ErrorColumnName = "Row error";
      }
      Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);
  }
1
sorrell

Je me suis connecté à la page Web du message d'erreur SSIS avec Excel à l'aide de la commande Obtenir les données du Web dans l'onglet Données. Enregistré la table dans une feuille dans Excel, puis importé dans SQL Server. Puis l'a rejoint à ma table de lignes d'erreur sur le code décimal pour obtenir la description, puis a créé une vue à partir de celle-ci. Cela pourrait être utile pour ceux qui ne veulent pas jouer avec la tâche de script.

1
Brandon Frenchak

Je me tirais les cheveux depuis deux jours. J'ai fait tout ce qui est mentionné partout mais le paquet/c # jetait une erreur. Finalement, quand j'ai décidé d'abandonner, j'ai trouvé que mon ErrorColumn montait à 0 (zéro) parce que l'erreur était dans la ligne entière à cause d'une violation de contrainte PK/FK.

J'ai donc modifié le script comme ci-dessous:

public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);

        var componentMetaData130 = this.ComponentMetaData as IDTSComponentMetaData130;
        if (componentMetaData130 != null)
        {
            if (Row.ErrorColumn == 0) //Checking if the Column is zero
            {
                Row.ColumnName = "Entire Row. Check PK FK constraints"; //Hardcoded error message
            }
            else
            {
                Row.ColumnName = componentMetaData130.GetIdentificationStringByID(Row.ErrorColumn);
            }
        }
    }

Pour le processus habituel: https://docs.Microsoft.com/en-us/sql/integration-services/extending-packages-scripting-data-flow-script-express-exemples/enhancing-an-error-outputput- avec le composant de script? view = sql-server-2017

Pourquoi la valeur ErrorColumn est-elle égale à zéro ?: SSIS 2016 - ErrorColumn vaut 0 (zéro)

J'espère que cela pourra aider !!!

0
Sabbir Hassan