Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come importare file di testo con lo stesso nome e schema ma directory diverse nel database?

Sì. Ti consigliamo di utilizzare un Foreach File Container e quindi seleziona l'opzione Attraversa sottocartella.

Modifica

Apparentemente la mia risposta non era abbastanza cromulente, quindi per favore accetta questo codice funzionante che illustra ciò che affermava la mia breve risposta originale.

Dati di origine

Ho creato 3 cartelle come descritto sopra per contenere i file sample1.txt e sample2.txt

C:\>MKDIR SSISDATA\SO\TEST\201304
C:\>MKDIR SSISDATA\SO\TEST\201305
C:\>MKDIR SSISDATA\SO\TEST\201306

Di seguito il contenuto del file. Ogni versione del file in ogni cartella ha il valore ID incrementato insieme ai valori di testo modificati per dimostrare che ha raccolto il nuovo file.

ID,value
1,ABC

Generazione di pacchetti

Questa parte presuppone che tu abbia BIDS Helper installato. Non è richiesto per la soluzione, ma fornisce semplicemente una struttura comune che i futuri lettori potrebbero utilizzare per riprodurre questa soluzione

Ho creato un file BIML con il seguente contenuto. Anche se ho il passaggio di creazione della tabella lì, dovevo eseguirlo sul server di destinazione prima di generare il pacchetto.

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <!-- Create a basic flat file source definition -->
    <FileFormats>
        <FlatFileFormat
            Name="FFFSrc"
            CodePage="1252"
            RowDelimiter="CRLF"
            IsUnicode="false"
            FlatFileType="Delimited"
            ColumnNamesInFirstDataRow="true"
        >
            <Columns>
                <Column
                    Name="ID"
                    DataType="Int32"
                    Delimiter=","
                    ColumnType="Delimited"
                />
                <Column
                    Name="value"
                    DataType="AnsiString"
                    Delimiter="CRLF"
                    InputLength="20"
                    MaximumWidth="20"
                    Length="20"
                    CodePage="1252"
                    ColumnType="Delimited"
                    />
            </Columns>
        </FlatFileFormat>
    </FileFormats>

    <!-- Create a connection that uses the flat file format defined above-->
    <Connections>
        <FlatFileConnection
            Name="FFSrc"
            FileFormat="FFFSrc"
            FilePath="C:\ssisdata\so\TEST\201306\sample1.txt"
            DelayValidation="true"
        />
        <OleDbConnection
            Name="tempdb"
            ConnectionString="Data Source=localhost\dev2012;Initial Catalog=tempdb;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;"
        />

    </Connections>

    <!-- Create a package to illustrate how to apply an expression on the Connection Manager -->
    <Packages>
        <Package
            Name="so_19957451"
            ConstraintMode="Linear"
        >
            <Connections>
                <Connection ConnectionName="tempdb"/>
                <Connection ConnectionName="FFSrc">
                    <Expressions>
                        <!-- Assign a variable to the ConnectionString property. 
                        The syntax for this is ConnectionManagerName.Property -->
                        <Expression PropertyName="FFSrc.ConnectionString">@[User::CurrentFileName]</Expression>
                    </Expressions>
                </Connection>
            </Connections>

            <!-- Create a single variable that points to the current file -->
            <Variables>
                <Variable Name="CurrentFileName" DataType="String">C:\ssisdata\so\TEST\201306\sample1.txt</Variable>
                <Variable Name="FileMask" DataType="String">*.txt</Variable>
                <Variable Name="SourceFolder" DataType="String">C:\ssisdata\so\TEST</Variable>
                <Variable Name="RowCountInput" DataType="Int32">0</Variable>
                <Variable Name="TargetTable" DataType="String">[dbo].[so_19957451]</Variable>
            </Variables>

            <!-- Add a foreach file enumerator. Use the above -->
            <Tasks>
                <ExecuteSQL 
                    Name="SQL Create Table"
                    ConnectionName="tempdb">
                    <DirectInput>
                        IF NOT EXISTS (SELECT * FROM sys.tables T WHERE T.name = 'so_19957451' and T.schema_id = schema_id('dbo'))
                        BEGIN
                            CREATE TABLE dbo.so_19957451(ID int NOT NULL, value varchar(20) NOT NULL);
                        END
                    </DirectInput>
                </ExecuteSQL>
                <ForEachFileLoop
                    Name="FELC Consume files"
                    FileSpecification="*.csv"
                    ProcessSubfolders="true"
                    RetrieveFileNameFormat="FullyQualified"
                    Folder="C:\"
                    ConstraintMode="Linear"
                >
                    <!-- Define the expressions to make the input folder and the file mask 
                    driven by variable values -->
                    <Expressions>
                        <Expression PropertyName="Directory">@[User::SourceFolder]</Expression>
                        <Expression PropertyName="FileSpec">@[User::FileMask]</Expression>
                    </Expressions>
                    <VariableMappings>
                        <!-- Notice that we use the convention of User.Variable name here -->
                        <VariableMapping
                            Name="0"
                            VariableName="User.CurrentFileName"
                        />
                    </VariableMappings>
                    <Tasks>
                        <Dataflow Name="DFT Import file" DelayValidation="true">
                            <Transformations>
                                <FlatFileSource Name="FFS Sample" ConnectionName="FFSrc"/>
                                <RowCount Name="RC Source" VariableName="User.RowCountInput"/>
                                <OleDbDestination 
                                    Name="OLE_DST"
                                    ConnectionName="tempdb">
                                    <TableFromVariableOutput VariableName="User.TargetTable"/>                                  
                                </OleDbDestination>
                            </Transformations>
                        </Dataflow>
                    </Tasks>
                </ForEachFileLoop>
            </Tasks>
        </Package>
    </Packages>
</Biml>

Fare clic con il pulsante destro del mouse sul file biml e selezionare Generate SSIS Package . A questo punto, dovresti avere un pacchetto chiamato so_19957451 aggiunto al tuo attuale progetto SSIS.

Configurazione del pacchetto

Non è necessaria alcuna configurazione perché è già stato fatto tramite BIML ma gli screenshot di moar forniscono risposte migliori.

Questo è il pacchetto base

Ecco le mie variabili

Configurazione del ciclo Foreach, come indicato nell'articolo MSDN e nella mia nota di selezionare la sottocartella Traverse

Assegna il valore generato per loop alla variabile Corrente

L'origine del file flat ha un'espressione applicata alla proprietà ConnectionString per assicurarsi che utilizzi la variabile @User::CurrentFileName. Questo cambia la sorgente per l'esecuzione del ciclo.

Risultati dell'esecuzione

Risultati dal database

Abbina l'output dell'esecuzione del pacchetto