Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Tâche SSIS pour l'importation incohérente du nombre de colonnes ?

De mémoire, j'ai une solution à 50 % pour vous.

Le problème

SSIS vraiment se soucie des métadonnées, de sorte que leurs variations ont tendance à entraîner des exceptions. DTS était beaucoup plus indulgent dans ce sens. Ce fort besoin de métadonnées cohérentes rend l'utilisation de la source de fichier plat gênante.

Solution basée sur des requêtes

Si le problème vient du composant, ne l'utilisons pas. Ce que j'aime dans cette approche, c'est que conceptuellement, c'est la même chose que d'interroger une table :l'ordre des colonnes n'a pas d'importance, pas plus que la présence de colonnes supplémentaires.

Variables

J'ai créé 3 variables, toutes de type chaîne :CurrentFileName, InputFolder et Query.

  • InputFolder est câblé au dossier source. Dans mon exemple, c'est C:\ssisdata\Kipreal
  • CurrentFileName est le nom d'un fichier. Au moment de la conception, c'était input5columns.csv mais cela changera au moment de l'exécution.
  • La requête est une expression "SELECT col1, col2, col3, col4, col5 FROM " + @[User::CurrentFilename]

Gestionnaire de connexion

Configurez une connexion au fichier d'entrée à l'aide du pilote JET OLEDB. Après l'avoir créé comme décrit dans l'article lié, je l'ai renommé FileOLEDB et défini une expression sur le ConnectionManager de "Data Source=" + @[User::InputFolder] + ";Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"text;HDR=Yes;FMT=CSVDelimited;\";"

Flux de contrôle

Mon flux de contrôle ressemble à une tâche de flux de données imbriquée dans un énumérateur de fichier Foreach

Énumérateur de fichiers Foreach

Mon énumérateur Foreach File est configuré pour fonctionner sur des fichiers. J'ai mis une expression sur le répertoire pour @[User::InputFolder] Notez qu'à ce stade, si la valeur de ce dossier doit changer, elle sera correctement mise à jour à la fois dans le gestionnaire de connexions et dans l'énumérateur de fichiers. Dans "Récupérer le nom du fichier", au lieu de "Complètement qualifié" par défaut, choisissez "Nom et extension"

Dans l'onglet Variable Mappings, attribuez la valeur à notre @[User::CurrentFileName] variables

À ce stade, chaque itération de la boucle modifiera la valeur de @[User::Query pour refléter le nom de fichier actuel.

Flux de données

C'est en fait la pièce la plus simple. Utilisez une source OLE DB et câblez-la comme indiqué.

Utilisez le gestionnaire de connexions FileOLEDB et changez le mode d'accès aux données en "Commande SQL à partir d'une variable". Utilisez le @[User::Query] variable là-dedans, cliquez sur OK et vous êtes prêt à travailler.

Exemples de données

J'ai créé deux exemples de fichiers input5columns.csv et input7columns.csv Toutes les colonnes de 5 sont en 7 mais 7 les a dans un ordre différent (col2 est la position ordinale 2 et 6). J'ai nié toutes les valeurs de 7 pour qu'il soit facilement évident sur quel fichier est opéré.

col1,col3,col2,col5,col4
1,3,2,5,4
1111,3333,2222,5555,4444
11,33,22,55,44
111,333,222,555,444

et

col1,col3,col7,col5,col4,col6,col2
-1111,-3333,-7777,-5555,-4444,-6666,-2222
-111,-333,-777,-555,-444,-666,-222
-1,-3,-7,-5,-4,-6,-2
-11,-33,-77,-55,-44,-666,-222

L'exécution du package donne ces deux captures d'écran

Ce qui manque

Je ne connais pas de moyen de dire à l'approche basée sur les requêtes que tout va bien si une colonne n'existe pas. S'il y a une clé unique, je suppose que vous pourriez définir votre requête pour n'avoir que les colonnes qui doivent être là, puis effectuer des recherches dans le fichier pour essayer d'obtenir les colonnes qui devraient être là et ne pas échouer la recherche si la colonne n'existe pas. Assez maladroit cependant.