Olá pessoal,
Boa noite!

Depois de escrever meu post anterior, onde falei sobre Como importar arquivos de texto para o banco (OLE Automation, CLR, BCP, BULK INSERT, OPENROWSET), acabei me animando pra escrever a parte 2, que é o processo inverso, ou seja, exportar os dados do SQL Server para um arquivo de texto, que é exatamente esse post.

Muitas vezes precisamos exportar dados de forma fácil para um arquivo de texto e já vi vários desenvolvedores ou DBA’s desesperados porque não sabem como fazer isso de forma eficiente.

Vamos resolver isso de uma vez por todas.

Exportando pelo SQL Server Management Studio

Como exportar dados pelo SQL Server Management Studio

Sem dúvida, a forma mais simples e fácil de exportar dados para arquivo no SQL Server é utilizando a própria interface da ferramenta, que é o Management Studio.

Na tela de Object Explorer, clique com o botão direito sobre o database que contém as tabelas que você deseja exportar e selecione a opção “Tasks” -> “Export Data…”

SQL Server - Export data to text file with Management Studio
SQL Server - Export data to text file with Management Studio

Nesta tela, você deve escolher a fonte de origem dos dados, configurar os dados de conexão e o database que você irá exportar

SQL Server - Export data to text file with Management Studio 2
SQL Server - Export data to text file with Management Studio 2

Nesta tela, você deve escolher a fonte de destino dos dados. Para arquivo, escolhi “Flat File Destination”. Podemos definir onde será gravado o arquivo com os dados, codificação dos caracteres (ISO-8859, UTF-8, etc), o formato dos dados no arquivo (delimitado por algum caractere, tamanho fixo ou alinhado à direita), o qualificador do texto (ex: se você definir o aspas como qualificador, a sua senha será algo assim: “Dirceu”;”29″;”DBA”) e definir se a primeira linha conterá o cabeçalho da tabela.

SQL Server - Export data to text file with Management Studio 3
SQL Server - Export data to text file with Management Studio 3

Nesta tela, você pode definir se você quer selecionar os objetos que deseja exportar (primeira opção) ou quer escrever uma query e o resultado da query será exportado para o arquivo. Para este exemplo, vou escolher a primeira opção.

SQL Server - Export data to text file with Management Studio 4
SQL Server - Export data to text file with Management Studio 4

Aqui você pode escolher o objeto que será exportado e definir o formato de quebra de linha (Windows = CRLF, UNIX = LF) e o caractere delimitador de colunas

SQL Server - Export data to text file with Management Studio 5
SQL Server - Export data to text file with Management Studio 5

Por fim, nesta tela você define se já quer exportar os dados (Run immediately) e se você desejar gerar um package do Integration Services (SSIS) caso queira automatizar essa tarefa como um Job pelo SQL Agent ou executá-la manualmente sem precisar configurar tudo de novo.

SQL Server - Export data to text file with Management Studio 6
SQL Server - Export data to text file with Management Studio 6

SQL Server - Export data to text file with Management Studio 7
SQL Server - Export data to text file with Management Studio 7

SQL Server - Export data to text file with Management Studio 8
SQL Server - Export data to text file with Management Studio 8

Embora isso seja simples, para exportar várias tabelas isso acaba sendo trabalhoso e nada prático. Por este motivo, eu vou explicar mais abaixo como fazer isso via T-SQL.

Exportando pelo BCP (Bulk Copy)

Como exportar dados do SQL Server para arquivo txt com BCP

Essa é uma das opções mais utilizadas pelos DBA’s, pois é simples, já vem instalada com o SQL Server e pode ser executada tanto em packages SSIS quanto em stored procedures (utilizando xp_cmdshell)

Lembrando que para utilizar o BCP, você precisará ativar o recurso xp_cmdshell. Eu particularmente não gosto de utilizar o xp_cmdshell e nem de deixar habilitado em uma instância, pois permite inúmeras vulnerabilidades e qualquer comando do Prompt do Windows pode ser executado com esse recurso habilitado.

Para ativar a feature e permitir o xp_cmdshell, execute os seguintes comandos:

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'xp_cmdshell', 1;
GO
RECONFIGURE;
GO

Exemplo de utilização:

-- Utilizando queryout, pode-se exportar o resultado de uma query
EXEC master.dbo.xp_cmdshell 'bcp "SELECT * FROM msdb.sys.tables" queryout "C:\Temp\bcp_queryout.csv" -c -t; -T -Slocalhost\SQL2014'

-- Utilizando out, pode-se exportar um objeto
EXEC master.dbo.xp_cmdshell 'bcp msdb.sys.tables out "C:\Temp\bcp_out.csv" -c -t, -T -Slocalhost\SQL2014'

SQL Server - Export data to CSV with BCP out queryout Results
SQL Server - Export data to CSV with BCP out queryout Results

Onde:
– out e queryout permitem definir a forma de exportação dos dados. OUT exporta um objeto e o QUERYOUT o resultado de uma query.
– -c define que todos os campos serão exportados como caracter (string)
– -t; permite definir o separador dos campos, não limitando-se a apenas 1 caractere como separador. No primeiro exemplo, estou utilizando o “;” como separador de coluna.
– -T serve para informar que a conexão será realizada no modo Trusted Connection (Autenticação Windows). Caso você queira utilizar autenticação SQL Server, basta utilizar -Uusuario e -Psenha.
– -S serve para informar o servidor\instância que você deseja se conectar.

Definições de parâmetros do BCP:

BCP Help
BCP Help

Exportando com OLE Automation

Como exportar arquivos de texto para o banco com OLE Automation

Para quem não conhece esse recurso, ele permite que o DBA ou Desenvolvedor execute uma série de ações no banco de dados usando OLE DB, como leitura/escrita/movimentação/cópia/deleção de arquivos, criação de planilhas no Excel e mais uma série de coisas. A sintaxe é um pouco parecida com o VBA e utiliza a API do Windows para essas operações.

Para essa finalidade, vamos utilizar as Stored Procedures stpEscreve_Arquivo_FSO e SaveDelimitedColumns, conforme demonstrado abaixo:

Código-fonte da Procedure stpEscreve_Arquivo_FSO

CREATE PROCEDURE [dbo].[stpEscreve_Arquivo_FSO] (
    @String VARCHAR(MAX),
    @Ds_Arquivo VARCHAR(1501)
)
AS
BEGIN

    DECLARE
        @objFileSystem INT,
        @objTextStream INT,
        @objErrorObject INT,
        @strErrorMessage VARCHAR(1000),
        @Command VARCHAR(1000),
        @hr INT

    SET NOCOUNT ON

    SELECT
        @strErrorMessage = 'opening the File System Object'
    
    EXECUTE @hr = sp_OACreate
        'Scripting.FileSystemObject',
        @objFileSystem OUT

    
    IF @hr = 0
        SELECT
            @objErrorObject = @objFileSystem,
            @strErrorMessage = 'Creating file "' + @Ds_Arquivo + '"'
    
    
    IF @hr = 0
        EXECUTE @hr = sp_OAMethod
            @objFileSystem,
            'CreateTextFile',
            @objTextStream OUT,
            @Ds_Arquivo,
            2,
            True

    IF @hr = 0
        SELECT
            @objErrorObject = @objTextStream,
            @strErrorMessage = 'writing to the file "' + @Ds_Arquivo + '"'
    
    
    IF @hr = 0
        EXECUTE @hr = sp_OAMethod
            @objTextStream,
            'Write',
            NULL,
            @String

    
    IF @hr = 0
        SELECT
            @objErrorObject = @objTextStream,
            @strErrorMessage = 'closing the file "' + @Ds_Arquivo + '"'
    
    
    IF @hr = 0
        EXECUTE @hr = sp_OAMethod
            @objTextStream,
            'Close'

    
    IF @hr <> 0
    BEGIN
    
        DECLARE
            @Source VARCHAR(255),
            @Description VARCHAR(255),
            @Helpfile VARCHAR(255),
            @HelpID INT
    
        EXECUTE sp_OAGetErrorInfo
            @objErrorObject,
            @Source OUTPUT,
            @Description OUTPUT,
            @Helpfile OUTPUT,
            @HelpID OUTPUT
        
        
        SELECT
            @strErrorMessage = 'Error whilst ' + COALESCE(@strErrorMessage, 'doing something') + ', ' + COALESCE(@Description, '')
        
        
        RAISERROR (@strErrorMessage,16,1)
        
    END
    
    
    EXECUTE sp_OADestroy
        @objTextStream
    
    EXECUTE sp_OADestroy
        @objTextStream
        
END

Código-fonte da Procedure SaveDelimitedColumns
Para visualizar o código-fonte dessa procedure, criada pelo John Buoro, acesse este link ou abaixo:

CREATE PROCEDURE [dbo].[SaveDelimitedColumns]
    @PCWrite VARCHAR(1000) = NULL,
    @DBFetch VARCHAR(4000),
    @DBWhere VARCHAR(2000) = NULL,
    @DBThere VARCHAR(2000) = NULL,
    @DBUltra BIT = 1,
    @Delimiter VARCHAR(100) = 'CHAR(44)', -- Default is ,
    @TextQuote VARCHAR(100) = 'CHAR(34)', -- Default is "  Use SPACE(0) for none.
    @Header BIT = 0, -- Output header. Default is 0.
    @NullQuoted BIT = 0,
    @DateTimeStyle TINYINT = 120 -- CONVERT Date Time Style. Default is ODBC canonical yyyy-mm-dd hh:mi:ss(24h)
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @Return INT;
    DECLARE @Retain INT;
    DECLARE @Status INT;

    SET @Status = 0;

    DECLARE @TPre VARCHAR(10);

    DECLARE @TDo3 TINYINT;
    DECLARE @TDo4 TINYINT;

    SET @TPre = '';

    SET @TDo3 = LEN(@TPre);
    SET @TDo4 = LEN(@TPre) + 1;

    DECLARE @DBAE VARCHAR(40);
    DECLARE @Task VARCHAR(6000);
    DECLARE @Bank VARCHAR(4000);
    DECLARE @Cash VARCHAR(2000);
    DECLARE @Risk VARCHAR(2000);
    DECLARE @Next VARCHAR(8000);
    DECLARE @Save VARCHAR(8000);
    DECLARE @Work VARCHAR(8000);
    DECLARE @Wish VARCHAR(MAX);

    DECLARE @Name VARCHAR(100);
    DECLARE @Same VARCHAR(100);

    DECLARE @Rank SMALLINT;
    DECLARE @Kind VARCHAR(20);
    DECLARE @Mask BIT;
    DECLARE @Bond BIT;
    DECLARE @Size INT;
    DECLARE @Wide SMALLINT;
    DECLARE @More SMALLINT;

    DECLARE @DBAI VARCHAR(2000);
    DECLARE @DBAO VARCHAR(8000);
    DECLARE @DBAU VARCHAR(MAX);

    DECLARE @Fuse INT;
    DECLARE @File INT;

    DECLARE @HeaderString VARCHAR(8000);
    DECLARE @HeaderDone INT;

    SET @DBAE = '##SaveFile' + RIGHT(CONVERT(VARCHAR(10), @@SPID + 100000), 5);

    SET @Task = 'IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE name = ' + CHAR(39) + @DBAE + CHAR(39) + ') DROP TABLE ' + @DBAE;

    EXECUTE ( @Task );

    SET @Bank = @TPre + @DBFetch;

    IF NOT EXISTS
    (
        SELECT
            *
        FROM
            sysobjects
        WHERE
            RTRIM(type) = 'U'
            AND name = @Bank
    )
    BEGIN
        SET @Bank = CASE WHEN LEFT(LTRIM(@DBFetch), 6) = 'SELECT' THEN '(' + @DBFetch + ')' ELSE @DBFetch END;
        SET @Bank = REPLACE(@Bank, CHAR(94), CHAR(39));
        SET @Bank = REPLACE(@Bank, CHAR(45) + CHAR(45), CHAR(32));
        SET @Bank = REPLACE(@Bank, CHAR(47) + CHAR(42), CHAR(32));
    END;

    IF @DBWhere IS NOT NULL
    BEGIN
        SET @Cash = REPLACE(@DBWhere, 'WHERE', CHAR(32));
        SET @Cash = REPLACE(@Cash, CHAR(94), CHAR(39));
        SET @Cash = REPLACE(@Cash, CHAR(45) + CHAR(45), CHAR(32));
        SET @Cash = REPLACE(@Cash, CHAR(47) + CHAR(42), CHAR(32));
    END;

    IF @DBThere IS NOT NULL
    BEGIN
        SET @Risk = REPLACE(@DBThere, 'ORDER BY', CHAR(32));
        SET @Risk = REPLACE(@Risk, CHAR(94), CHAR(39));
        SET @Risk = REPLACE(@Risk, CHAR(45) + CHAR(45), CHAR(32));
        SET @Risk = REPLACE(@Risk, CHAR(47) + CHAR(42), CHAR(32));
    END;

    SET @DBAI = '';
    SET @DBAO = '';
    SET @DBAU = '';

    SET @Task = 'SELECT * INTO ' + @DBAE + ' FROM (' + @Bank + ') AS T WHERE 0 = 1';
    
    IF @Status = 0
        EXECUTE ( @Task );
    SET @Return = @@ERROR;
    IF @Status = 0
        SET @Status = @Return;

    -- For all columns (Fields) in the table.
    DECLARE Fields CURSOR FAST_FORWARD FOR
    SELECT
        '[' + C.name + ']',
        C.colid,
        T.name,
        C.isnullable,
        C.iscomputed,
        C.length,
        C.prec,
        C.scale
    FROM
        tempdb.dbo.sysobjects AS O
        JOIN tempdb.dbo.syscolumns AS C ON O.id = C.id
        JOIN tempdb.dbo.systypes AS T ON C.xusertype = T.xusertype
    WHERE
        O.name = @DBAE
    ORDER BY
        C.colid;

    SET @Retain = @@ERROR;
    IF @Status = 0
        SET @Status = @Retain;

    OPEN Fields;

    SET @Retain = @@ERROR;
    IF @Status = 0
        SET @Status = @Retain;

    FETCH NEXT FROM Fields
    INTO
        @Same,
        @Rank,
        @Kind,
        @Mask,
        @Bond,
        @Size,
        @Wide,
        @More;

    SET @Retain = @@ERROR;
    IF @Status = 0
        SET @Status = @Retain;

    -- Convert to character for header.
    SET @HeaderString = '';
    DECLARE @sql NVARCHAR(4000);
    DECLARE @cDelimiter NVARCHAR(9);
    DECLARE @cTextQuote NVARCHAR(9);
    DECLARE @TypeFound BIT;
    SET @sql = N'select @cDelimiter = ' + @Delimiter;
    EXEC sp_executesql @sql, N'@cDelimiter varchar(9) output', @cDelimiter OUTPUT;
    SET @sql = N'select @cTextQuote = ' + @TextQuote;
    EXEC sp_executesql @sql, N'@cTextQuote varchar(9) output', @cTextQuote OUTPUT;

    WHILE @@FETCH_STATUS = 0
          AND @Status = 0
    BEGIN
        SET @TypeFound = 0;

        -- Build header.
        IF LEN(@HeaderString) > 0
            SET @HeaderString = @HeaderString + @cDelimiter + ISNULL(@cTextQuote + REPLACE(@Same, @cTextQuote, REPLICATE(@cTextQuote, 2)) + @cTextQuote, SPACE(0));
        IF LEN(@HeaderString) = 0
            SET @HeaderString = ISNULL(@cTextQuote + REPLACE(@Same, @cTextQuote, REPLICATE(@cTextQuote, 2)) + @cTextQuote, SPACE(0));

        IF @Kind IN ( 'char', 'nchar', 'varchar', 'nvarchar', 'text', 'ntext', 'sysname', 'xml' )
        BEGIN
            IF @NullQuoted = 0
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+REPLACE(' + @Same + ' COLLATE SQL_Latin1_General_CP1_CI_AI,' + @TextQuote + ',REPLICATE(' + @TextQuote + ',2))+' + @TextQuote + ',SPACE(0))';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+REPLACE(' + @Same + ' COLLATE SQL_Latin1_General_CP1_CI_AI,' + @TextQuote + ',REPLICATE(' + @TextQuote + ',2))+' + @TextQuote + ',SPACE(0))';
            END;
            IF @NullQuoted = 1
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+REPLACE(' + @Same + ' COLLATE SQL_Latin1_General_CP1_CI_AI,' + @TextQuote + ',REPLICATE(' + @TextQuote + ',2))+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+REPLACE(' + @Same + ' COLLATE SQL_Latin1_General_CP1_CI_AI,' + @TextQuote + ',REPLICATE(' + @TextQuote + ',2))+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
            END;
            SET @TypeFound = 1;
        END;

        IF @Kind IN ( 'bit', 'tinyint', 'smallint', 'int', 'bigint' )
        BEGIN
            IF @NullQuoted = 0
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(CONVERT(varchar(128),' + @Same + '),SPACE(0))';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(CONVERT(varchar(128),' + @Same + '),SPACE(0))';
            END;
            IF @NullQuoted = 1
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(CONVERT(varchar(128),' + @Same + '),' + @TextQuote + '+' + @TextQuote + ')';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(CONVERT(varchar(128),' + @Same + '),' + @TextQuote + '+' + @TextQuote + ')';
            END;
            SET @TypeFound = 1;
        END;

        IF @Kind IN ( 'numeric', 'decimal', 'money', 'smallmoney', 'float', 'real' )
        BEGIN
            IF @NullQuoted = 0
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(CONVERT(varchar(128),' + @Same + '),SPACE(0))';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(CONVERT(varchar(128),' + @Same + '),SPACE(0))';
            END;
            IF @NullQuoted = 1
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(CONVERT(varchar(128),' + @Same + '),' + @TextQuote + '+' + @TextQuote + ')';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(CONVERT(varchar(128),' + @Same + '),' + @TextQuote + '+' + @TextQuote + ')';
            END;
            SET @TypeFound = 1;
        END;

        IF @Kind IN ( 'uniqueidentifier', 'geometry', 'geography' )
        BEGIN
            IF @NullQuoted = 0
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ')+' + @TextQuote + ',SPACE(0))';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ')+' + @TextQuote + ',SPACE(0))';
            END;
            IF @NullQuoted = 1
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ')+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ')+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
            END;
            SET @TypeFound = 1;
        END;

        IF @Kind IN ( 'datetime2', 'datetime', 'smalldatetime', 'time', 'date', 'datetimeoffset' )
        BEGIN
            IF @NullQuoted = 0
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ',' + CONVERT(VARCHAR(3), @DateTimeStyle) + ')+' + @TextQuote + ',SPACE(0))';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ',' + CONVERT(VARCHAR(3), @DateTimeStyle) + ')+' + @TextQuote + ',SPACE(0))';
            END;
            IF @NullQuoted = 1
            BEGIN
                IF @Rank = 1
                    SET @DBAU = ' ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ',' + CONVERT(VARCHAR(3), @DateTimeStyle) + ')+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
                IF @Rank > 1
                    SET @DBAU = @DBAU + '+' + @Delimiter + '+ISNULL(' + @TextQuote + '+CONVERT(varchar(128),' + @Same + ',' + CONVERT(VARCHAR(3), @DateTimeStyle) + ')+' + @TextQuote + ',' + @TextQuote + '+' + @TextQuote + ')';
            END;
            SET @TypeFound = 1;
        END;

        IF @TypeFound = 0
        BEGIN
            SET @Retain = 'ERROR: Data type ' + UPPER(@Kind) + ' was used but not supported by SaveDelimitedColumns.';
            SET @Status = @Retain;
        END;

        FETCH NEXT FROM Fields
        INTO
            @Same,
            @Rank,
            @Kind,
            @Mask,
            @Bond,
            @Size,
            @Wide,
            @More;

        SET @Retain = @@ERROR;
        IF @Status = 0
            SET @Status = @Retain;
    END;

    CLOSE Fields;
    DEALLOCATE Fields;

    IF LEN(@DBAU) = 0
        SET @DBAU = '*';

    IF @PCWrite IS NOT NULL
       AND ( @DBUltra = 0 )
       AND ( @Header = 1 )
    BEGIN
        SET @HeaderString = REPLACE(@HeaderString, '"', '""');
        SET @DBAI = ' SELECT ' + CHAR(39) + @HeaderString + CHAR(39) + ' UNION ALL SELECT ';
    END;
    ELSE
        SET @DBAI = ' SELECT ';

    SET @DBAO = ' FROM (' + @Bank + ') AS T' + CASE WHEN @DBWhere IS NULL THEN '' ELSE ' WHERE (' + @Cash + ') AND 0 = 0' END + CASE WHEN @DBThere IS NULL THEN '' ELSE ' ORDER BY ' + @Risk END;

    -- Output where @DBUltra = 0 (Uses XP_CMDSHELL \ BCP)
    IF @PCWrite IS NOT NULL
       AND @DBUltra = 0
    BEGIN
        SET @Wish = 'USE ' + DB_NAME() + @DBAI + @DBAU + @DBAO;
        SET @Work = 'BCP "' + @Wish + '" QUERYOUT "' + @PCWrite + '" -w -T -S "' + @@SERVERNAME + '" ';
        -- PRINT @Work
        EXECUTE @Return = master.dbo.xp_cmdshell @Work, NO_OUTPUT;
        SET @Retain = @@ERROR;
        IF @Status = 0
            SET @Status = @Retain;
        IF @Status = 0
            SET @Status = @Return;

        IF @Status <> 0
            GOTO ABORT;
    END;

    -- Output where @DBUltra = 1 (Uses Ole Automation)
    IF @PCWrite IS NOT NULL
       AND @DBUltra = 1
    BEGIN
        IF @Status = 0
            EXECUTE @Return = sp_OACreate 'Scripting.FileSystemObject', @Fuse OUTPUT;
        SET @Retain = @@ERROR;
        IF @Status = 0
            SET @Status = @Retain;
        IF @Status = 0
            SET @Status = @Return;

        IF @Status = 0
            EXECUTE @Return = sp_OAMethod @Fuse, 'CreateTextFile', @File OUTPUT, @PCWrite, -1;
        SET @Retain = @@ERROR;
        IF @Status = 0
            SET @Status = @Retain;
        IF @Status = 0
            SET @Status = @Return;

        IF @Status <> 0
            GOTO ABORT;
    END;

    SET @DBAI = 'DECLARE Records CURSOR GLOBAL FAST_FORWARD FOR' + @DBAI;

    
    IF @Status = 0
        EXECUTE ( @DBAI + @DBAU + @DBAO );
    SET @Return = @@ERROR;
    IF @Status = 0
        SET @Status = @Return;

    OPEN Records;
    SET @Retain = @@ERROR;
    IF @Status = 0
        SET @Status = @Retain;

    FETCH NEXT FROM Records
    INTO
        @Next;
    SET @Retain = @@ERROR;
    IF @Status = 0
        SET @Status = @Retain;

    -- Header.
    SET @HeaderDone = 0;
    WHILE @@FETCH_STATUS = 0
          AND @Status = 0
    BEGIN
        IF @PCWrite IS NOT NULL
           AND @DBUltra = 1
        BEGIN
            -- Write header (FILE).
            IF ( @Header = 1 )
               AND ( @HeaderDone = 0 )
            BEGIN
                SET @Save = @HeaderString + CHAR(13) + CHAR(10);
                IF @Status = 0
                    EXECUTE @Return = sp_OAMethod @File, 'Write', NULL, @Save;
                SET @HeaderDone = 1;
            END;

            -- Write the data (FILE).
            SET @Save = @Next + CHAR(13) + CHAR(10);
            IF @Status = 0
                EXECUTE @Return = sp_OAMethod @File, 'Write', NULL, @Save;
            IF @Status = 0
                SET @Status = @Return;
        END;

        IF @PCWrite IS NULL
        BEGIN
            -- Print header (TEXT).
            IF ( @Header = 1 )
               AND ( @HeaderDone = 0 )
            BEGIN
                PRINT @HeaderString + CHAR(13) + CHAR(10);
                SET @HeaderDone = 1;
            END;
            PRINT @Next;
        END;

        FETCH NEXT FROM Records
        INTO
            @Next;
        SET @Retain = @@ERROR;
        IF @Status = 0
            SET @Status = @Retain;
    END;

    CLOSE Records;
    DEALLOCATE Records;

    -- Close output file (Ole Automation)
    IF @PCWrite IS NOT NULL
       AND @DBUltra = 1
    BEGIN
        EXECUTE @Return = sp_OAMethod @File, 'Close', NULL;
        IF @Status = 0
            SET @Status = @Return;

        EXECUTE @Return = sp_OADestroy @File;
        IF @Status = 0
            SET @Status = @Return;

        EXECUTE @Return = sp_OADestroy @Fuse;
        IF @Status = 0
            SET @Status = @Return;
    END;

    ABORT: -- This label is referenced when OLE automation fails.

    IF @Status = 1 OR @Status NOT BETWEEN 0 AND 50000
        RAISERROR('SaveDelimitedColumns Windows Error [%d]', 16, 1, @Status);

    SET @Task = 'IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE name = ' + CHAR(39) + @DBAE + CHAR(39) + ') DROP TABLE ' + @DBAE;
    EXECUTE ( @Task );

    RETURN ( @Status );

END;
GO

Exemplo de utilização:

-- Exportando uma string para arquivo com OLE Automation
DECLARE @Texto VARCHAR(MAX) = 'Teste
de arquivo

com quebra
de
linhas
'

EXEC dbo.stpEscreve_Arquivo_FSO 
    @String = @Texto, -- varchar(max)
    @Ds_Arquivo = 'C:\Temp\Teste.txt' -- varchar(1501)


-- Exportando para CSV com OLE Automation
EXEC dbo.SaveDelimitedColumns
    @DBFetch='select * from Testes.dbo.Teste',
    @DBWhere='Tipo = ^Teste 2^',
    @PCWrite='C:\Temp\Teste.csv',
    @Header = 1

SQL Server - Export data to text file with OLE Automation 2
SQL Server - Export data to text file with OLE Automation 2

Exportando com Common Language Runtime (CLR)

Como exportar arquivos de texto para o banco com CLR

O CLR permite que você consiga criar rotinas (stored prodecures, functions, triggers, etc) escritas em C#, F# e VB.NET, compilá-las e executá-las no banco de dados nativamente, estendendo as capacidades do SGBD, pois é possível criar uma infinidade de coisas que não seriam possíveis utilizando apenas o Transact-SQL, como manipulação de arquivos, upload e download de arquivos via FTP, funções de agregação, integração com Webservices e muito mais.

Para essa finalidade, vamos utilizar Stored Procedures stpExporta_Query_Txt e stpEscreve_Arquivo, conforme demonstrado abaixo:

Código-fonte da procedure stpExporta_Query_Txt

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Globalization;
using System.Text;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void stpExporta_Query_Txt(string query, string separador, string caminho, int Fl_Coluna)
    {

        var fileStream = new FileStream(caminho, FileMode.Create);
        var sw = new StreamWriter(fileStream, Encoding.Default);

        try
        {
            using (var conn = new SqlConnection("context connection=true"))
            {

                var getOutput = new SqlCommand
                {
                    CommandText = query,
                    CommandType = CommandType.Text,
                    CommandTimeout = 120,
                    Connection = conn
                };

                
                conn.Open();

                var exportData = getOutput.ExecuteReader();

                if (Fl_Coluna == 1)
                {
                    for (var i = 0; i < exportData.FieldCount; i++)
                    {
                        sw.Write(exportData.GetName(i));
                        if (i < exportData.FieldCount - 1)
                            sw.Write(separador);
                    }
                    sw.WriteLine();
                }

                if (string.IsNullOrEmpty(separador))
                {
                    while (exportData.Read())
                    {
                        for (var i = 0; i < exportData.FieldCount; i++)
                        {
                            sw.Write(Convert.ToString(exportData.GetValue(i), CultureInfo.GetCultureInfo("pt-BR")));
                            if (i < exportData.FieldCount - 1)
                                sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }
                else
                {
                    var separadorTroca = new string(' ', separador.Length);

                    while (exportData.Read())
                    {
                        for (var i = 0; i < exportData.FieldCount; i++)
                        {
                            sw.Write(Convert.ToString(exportData.GetValue(i), CultureInfo.GetCultureInfo("pt-BR")).Replace(separador, separadorTroca));
                            if (i < exportData.FieldCount - 1)
                                sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }


                conn.Close();
                sw.Close();
                conn.Dispose();
                getOutput.Dispose();

            }

        }
        catch (Exception e)
        {
            sw.Close();
            throw new ApplicationException("Erro : " + e.Message);
        }
    }
};

Código-fonte da procedure stpEscreve_Arquivo

using System;
using System.Data.SqlTypes;
using System.IO;
using System.Text;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void stpEscreve_Arquivo(SqlString Ds_Texto, SqlString Ds_Caminho, SqlString Ds_Codificacao, SqlString Ds_Formato_Quebra_Linha, SqlBoolean Fl_Append)
    {


        if (!Ds_Texto.IsNull && !Ds_Caminho.IsNull && !Fl_Append.IsNull)
        {

            try
            {

                var dir = Path.GetDirectoryName(Ds_Caminho.Value);

                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);

            }
            catch (Exception e)
            {
                throw new ApplicationException("Erro : " + e.Message);
            }


            var encoding = (Ds_Codificacao.IsNull) ? "UTF-8" : Ds_Codificacao.Value;
            if (Ds_Codificacao.Value.Trim() == "")
                encoding = "UTF-8";

            var sb = new StringBuilder(Ds_Texto.Value);

            var fileStream = new FileStream(Ds_Caminho.Value, ((Fl_Append) ? FileMode.Append : FileMode.Create));
            var sw = new StreamWriter(fileStream, Encoding.GetEncoding(encoding));

            switch (Ds_Formato_Quebra_Linha.Value.ToLower())
            {
                case "unix":
                    sw.NewLine = "\n";
                    sb.Replace("\r", "");
                    break;
                case "mac":
                    sw.NewLine = "\r";
                    sb.Replace("\n", "");
                    break;
                default:
                    sw.NewLine = "\r\n";
                    break;
            }


            try
            {

                var texto = sb.ToString();

                sw.Write(texto);
                sw.Close();

            }
            catch (Exception e)
            {
                sw.Close();
                throw new ApplicationException("Erro : " + e.Message);
            }

        }
        else
            throw new ApplicationException("Os parâmetros de input estão vazios");

    }
};

Exemplo de utilização:

-- Exportando uma string para arquivo texto
DECLARE @Texto VARCHAR(MAX) = 'Testando
Arquivo texto

com
quebra
de
linhas'

EXEC CLR.dbo.stpEscreve_Arquivo 
    @Ds_Texto = @Texto, -- nvarchar(max)
    @Ds_Caminho = N'C:\Temp\CLR_Texto.txt', -- nvarchar(max)
    @Ds_Codificacao = N'ISO-8859-1', -- nvarchar(max)
    @Ds_Formato_Quebra_Linha = N'windows', -- nvarchar(max)
    @Fl_Append = 0 -- bit


-- Exportando query para arquivo texto (CSV)
EXEC CLR.dbo.stpExporta_Query_Txt 
    @query = N'SELECT * FROM sys.tables', -- nvarchar(max)
    @separador = N';', -- nvarchar(max)
    @caminho = N'C:\Temp\CLR_Teste.csv', -- nvarchar(max)
    @Fl_Coluna = 1 -- int

SQL Server - Export data to CSV with CLR (C#) Results
SQL Server - Export data to CSV with CLR (C#) Results

É isso aí, pessoal!
Até o próximo post.

sql server exportar dados arquivo texto txt export data text files from database do banco de dados

sql server exportar dados arquivo texto txt export data text files from database do banco de dados