sql >> Database >  >> RDS >> Sqlserver

SSIS-taak voor het importeren van inconsistente kolommentelling?

Uit mijn hoofd, ik heb een oplossing van 50% voor je.

Het probleem

SSIS echt geeft om metadata, dus variaties daarin leiden tot uitzonderingen. DTS was in die zin veel vergevingsgezinder. Die sterke behoefte aan consistente metadata maakt het gebruik van de Flat File Source lastig.

Op zoekvraag gebaseerde oplossing

Als het probleem het onderdeel is, laten we het dan niet gebruiken. Wat ik leuk vind aan deze benadering is dat het conceptueel hetzelfde is als het opvragen van een tabel:de volgorde van kolommen doet er niet toe en de aanwezigheid van extra kolommen doet er niet toe.

Variabelen

Ik heb 3 variabelen gemaakt, allemaal van het type string:CurrentFileName, InputFolder en Query.

  • InputFolder is vast verbonden met de bronmap. In mijn voorbeeld is het C:\ssisdata\Kipreal
  • CurrentFileName is de naam van een bestand. Tijdens de ontwerptijd was het input5columns.csv maar dat zal tijdens runtime veranderen.
  • Query is een uitdrukking "SELECT col1, col2, col3, col4, col5 FROM " + @[User::CurrentFilename]

Verbindingsmanager

Maak een verbinding met het invoerbestand met behulp van het JET OLEDB-stuurprogramma. Nadat ik het had gemaakt zoals beschreven in het gekoppelde artikel, hernoemde ik het naar FileOLEDB en stelde ik een expressie in op de ConnectionManager van "Data Source=" + @[User::InputFolder] + ";Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"text;HDR=Yes;FMT=CSVDelimited;\";"

Besturingsstroom

Mijn controlestroom ziet eruit als een gegevensstroomtaak die is genest in een Forreach-bestandsenumerator

Foreach-bestandsteller

My Forreach File-enumerator is geconfigureerd om met bestanden te werken. Ik heb een uitdrukking in de directory geplaatst voor @[User::InputFolder] Merk op dat op dit punt, als de waarde van die map moet veranderen, deze correct zal worden bijgewerkt in zowel de Verbindingsmanager als de bestandsenumerator. Kies in "Bestandsnaam ophalen", in plaats van de standaard "Volledig gekwalificeerd", "Naam en extensie"

Wijs op het tabblad Variabele toewijzingen de waarde toe aan onze @[User::CurrentFileName] variabel

Op dit punt verandert elke iteratie van de lus de waarde van de @[User::Query om de huidige bestandsnaam weer te geven.

Gegevensstroom

Dit is eigenlijk het gemakkelijkste stuk. Gebruik een OLE DB-bron en sluit deze aan zoals aangegeven.

Gebruik de FileOLEDB-verbindingsbeheerder en wijzig de modus voor gegevenstoegang in "SQL-opdracht van variabele". Gebruik de @[User::Query] variabele daar in, klik op OK en je bent klaar om te werken.

Voorbeeldgegevens

Ik heb twee voorbeeldbestanden gemaakt input5columns.csv en input7columns.csv Alle kolommen van 5 staan ​​in 7, maar 7 heeft ze in een andere volgorde (col2 is ordinale positie 2 en 6). Ik heb alle waarden in 7 genegeerd om duidelijk te maken met welk bestand wordt gewerkt.

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

en

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

Het uitvoeren van het pakket resulteert in deze twee screenshots

Wat ontbreekt

Ik ken geen manier om de op query's gebaseerde benadering te vertellen dat het OK is als een kolom niet bestaat. Als er een unieke sleutel is, neem ik aan dat u uw zoekopdracht zo kunt definiëren dat deze alleen de kolommen heeft die moeten wees erbij en voer vervolgens zoekopdrachten uit op het bestand om te proberen de kolommen te verkrijgen die zou moeten om daar te zijn en de zoekopdracht niet te mislukken als de kolom niet bestaat. Wel behoorlijk kludgey.



  1. UPDATE meerdere tabellen in MySQL met LEFT JOIN

  2. Getallen opmaken met een min/plusteken in Oracle

  3. Postgres/JSON - update alle array-elementen

  4. PostgreSQL Cloud Vendor Lock-in vermijden