SSIS : lookup et gestion des rejets

Vous utilisez le composant recherche (lookup) dans SSIS pour vérifier l'intégrité et, je l'espère, pour rediriger les rejets éventuels.
Le problème est que personne ne regarde jamais les lignes rejetées, car le package SSIS se déroule sans erreur. Cet article vous propose une solution à ce problème.

Fonctionnement de la transformation Lookup

La transformation LOOKUP effectue une équi-jointure entre les valeurs de l'entrée et celles du dataset de référence. Chaque ligne de l'entrée de la transformation doit correspondre à au moins une ligne du dataset de référence.
  


Le composant peut être configuré pour gérer les non-correspondances de manière différente :
  • Se mettre en échec si non-correspondance (Composant défaillant, comportement par défaut)
  • ignorer les erreurs (toutes les lignes seront conservées qu’il y ait correspondance ou non)
  • rediriger les lignes sans correspondance vers une sortie de non correspondance ou d’erreur.


Problématique   

  • Lorsque le comportement par défaut est sélectionné (composant défaillant), en cas de non correspondance le composant bloque l’exécution du package sans que l’on obtienne d’information sur la ou les lignes ayant provoqué le problème.
  • Lorsque les lignes sans correspondances sont redirigées, aucune erreur n’est déclenchée : on n’est donc pas averti du problème, sauf à examiner les fichiers ou tables de rejet.
  • Dans tous les cas, le journal d’exécution ne nous donne pas une information facilement lisible pour localiser l’erreur rencontrée.

Objectif

L’objectif de cette procédure est donc :
pour chaque data flow
  • récupérer les lignes de non correspondance vers un fichier : pour plus de lisibilité, ce fichier ne doit être créé que si un rejet est rencontré.
  • Ne pas bloquer l’exécution du package pour un rejet
  • Envoyer l’information lisible sur le nombre de lignes de rejet et le data flow concerné dans le journal d’exécution.
Pour le package
  • Renvoyer un statut d’erreur d’exécution pour le package si au moins un des lookups a rejeté des lignes.

Mise en oeuvre

Déclarer des variables de package
Créer 4 variables : type int, étendue package
  • ErrorCount
  • FailedRows
  • RowCount
  • TotalFailedRows

Configuration des data flows
Configurer les lookups concernés pour rediriger les rejets vers la sortie sans correspondance

 

Organiser les lookups de manière à récupérer l’ensemble des rejets des lookup successifs
Utiliser un composant UNION ALL pour consolider tous les rejets

 

 
Stocker le nombre de lignes rejetées dans la variable User ::failedRows






Envoyer les rejets vers une destination texte plat délimité
Créez le nouveau gestionnaire de connexion et configurez le nom du fichier et le nom du gestionnaire de connexion.
Le format de nom du fichier destination est par exemple NomDuPackage_NomDuDataFlow.txt



 Créer un gestionnaire d’évènement OnPostExecute sur le Dataflow et y disposer un composant script et un composant système de fichiers



 
Composant script

Il teste la presence de lignes sans correspondance, déclenche une erreur si il y en a, met à jour les compteurs d’erreur.

 
  • Nom : Failed rows test
  • Langage : VB
  • Variables ReadOnly : System::SourceName,User::FailedRows
  • Variables ReadWrite : User::ErrorCount,User::TotalFailedRows

Code:

Public Sub Main()
        If Dts.Variables("User::FailedRows").Value > 0 Then
            Dts.Variables("User::ErrorCount").Value = Dts.Variables("User::ErrorCount").Value + 1
            Dts.Variables("User::TotalFailedRows").Value = Dts.Variables("User::TotalFailedRows").Value + Dts.Variables("User::FailedRows").Value
            Dts.Events.FireError(0, "Lookup Failed Rows", Dts.Variables("System::SourceName").Value + " : " + Str(Dts.Variables("User::FailedRows").Value) + " rows failed lookups", String.Empty, 0)
        End If
        Dts.TaskResult = ScriptResults.Success
    End Sub

Configurer la propriété MaximumErrorCount du composant script à 2


 
Tâche de système de fichiers : supprime le fichier de rejet


    

Contrainte d’enchaînement
  • Si succès et @[User ::FailedRows]==0
(ne supprime le fichier que s’il n’a pas de lignes en rejet

  



 
Configuration du package

Disposer une tache de script comme dernière tâche du package
  • Cette tâche met le package en erreur si des rejets ont été rencontrés

  •  Nom : Check for errors
  • Langage : VB
  • Variables ReadOnly : User::ErrorCount,User::TotalFailedRows
 

Code :
    Public Sub Main()
        'MsgBox("Errors : " + Str(Dts.Variables("User::ErrorCount").Value) + ", Failed Rows : " + Str(Dts.Variables("User::TotalFailedRows").Value))
        If Dts.Variables("User::ErrorCount").Value > 0 Then
            Dts.Events.FireError(0, "Lookup Failed Errors", "Total Lookup Failed Errors : " + Str(Dts.Variables("User::ErrorCount").Value) + ", Total Failed Rows : " + Str(Dts.Variables("User::TotalFailedRows").Value), String.Empty, 0)
            Dts.TaskResult = ScriptResults.Failure
        Else
            Dts.TaskResult = ScriptResults.Success
        End If
    End Sub


Et voilà, bon rejets...!