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:
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
.
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.
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 ....
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.
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
Entrée et sortie add Colonnes de sortie
(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);
}
}
//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));
Voici une solution qui
Découvrez la solution complète ici.
Voici la version courte.
execsObj
et lineageIds
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);
}
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.
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 !!!