Gravando o resultado selecionado em um arquivo CSV

37

Precisamos gravar os resultados da consulta SELECT em um arquivo csv. Como isso pode ser feito usando o T-SQL no SQL Server 2008 r2? Eu sei que isso pode ser feito no SSIS, mas por alguns motivos, não temos essa opção.

Tentei usar o processo sugerido no artigo abaixo, mas quando executo o processo, o SQL reclama que não pode executar sys.sp_OACreate e sys.sp_OADestroy, que são chamados nesse processo.

Você sabe como podemos ativar esses componentes ou conhece melhor maneira de gravar em um arquivo usando o T-SQL?

Desde já, obrigado.

Céu
fonte

Respostas:

52

Use o utilitário BCP

bcp "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable" queryout "D:\MyTable.csv" -c -t , -S SERVERNAME -T

Os -cespecifica argumento c saída haracter, em oposição ao formato binário nativo do SQL; Esse padrão para valores separados por tabulação, mas -t ,altera o campo t erminator para vírgulas. -Tautenticação especifica do Windows ( " t conexão enferrujada"), caso contrário usar -U MyUserName -P MyPassword.

Isso não exporta cabeçalhos de coluna por padrão. Você precisa usar um UNION ALL para cabeçalhos

OU

Use SQLCMD

SQLCMD -S SERVERNAME -E -Q "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable"
-s "," -o "D:\MyData.csv" 

OU

Use o PowerShell

Aqui está um link para um artigo . Se você acabar usando isso, poderá anexar -notypedepois Export-Csv $extractFilepara se livrar da coluna desnecessária no arquivo de saída.

RK Kuppala
fonte
4
+1 Para o utilitário BCP - é muito fácil de usar, é a ferramenta mais rápida que eu já usei para exportar / importar informações e há muitas opções. Vou aconselhá-lo a adicionar "> FileName.log" no final da instrução - isso criará um arquivo de log.
gotqn
24

Adicionando a resposta anterior, que ajuda a automatizar a ação, se você precisar apenas de tempos em tempos, pode fazê-lo no Management Studio, basta clicar com o botão direito do mouse no cabeçalho - Salvar resultados como -> escolher um arquivo .csv .

Ou, se você quiser fazer isso para cada instrução de seleção executada, poderá alterar a direção da saída dos resultados para um arquivo. Use Ferramentas -> Opções -> Resultados da consulta - Resultados para o arquivo .

Outra maneira, que pode ser automatizada facilmente e utiliza o SSIS, é usando o recurso Exportar Dados do Management Studio. Clique com o botão direito do mouse no banco de dados -> Tarefas -> Exportar dados. Há um assistente com muitas opções lá. Você deve escolher o banco de dados de origem, o destino e outras opções. Para o destino, verifique se é "Arquivo simples", procure e escolha o tipo .csv, escolha a formatação necessária e, no final, você obterá um pacote SSIS que pode ser salvo localmente e repetido conforme a necessidade.

Marian
fonte
10

Use T-SQL

INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0','Text;Database=D:\;HDR=YES;FMT=Delimited','SELECT * FROM [FileName.csv]')
SELECT Field1, Field2, Field3 FROM DatabaseName

Mas há algumas ressalvas:

  1. Você precisa ter o provedor Microsoft.ACE.OLEDB.12.0 disponível. O provedor Jet 4.0 também funcionará, mas é antigo, então usei este.
  2. O arquivo .CSV já deverá existir. Se você estiver usando cabeçalhos (HDR = YES), verifique se a primeira linha do arquivo .CSV é uma lista delimitada de todos os campos.
Slogmeister Extraordinaire
fonte
11
Melhor resposta até agora!
ajeh
11
bom trabalho, incluindo ressalvas
JJS
5

Baixa tecnologia, mas ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
fonte
O MySQL trata col1 + ',' + cast(col2 as varchar(10)) + ',' + col3como um nome de coluna e imprime NULL em todo o lugar.
Nikhil Wagh 24/10
4

Parece que você já tem uma solução aceitável, mas se você tiver o db mail configurado, poderá fazer algo assim:

EXEC msdb.dbo.sp_send_dbmail
    @recipients='[email protected]',
    @subject='CSV Extract', 
    @body='See attachment',
    @query ='SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'CSV_Extract.txt',
    @query_result_separator = ',',
    @query_result_header = 1

Se você estiver enviando o arquivo por e-mail para algum lugar de qualquer maneira, poderá economizar algumas etapas.

Shane Estelle
fonte
Apenas o que eu estava procurando, parabéns para você!
Mashchax
Embora você precise adicionar o parâmetro @profile_name se você não tiver um perfil privado padrão para o usuário nem um perfil público para o banco de dados.
Mashchax
1

Isso pode ser feito facilmente em um processo de 3 etapas:

  1. Escreva sua consulta como uma SELECT INTOconsulta. Isso basicamente exportará os resultados da sua consulta para uma tabela.

    Select
      Field1
     ,Field2
     ,Field3
    INTO dbo.LogTableName         --Table where the query Results get logged into.
    From Table

    Observe que essa tabela não pode existir quando a consulta é executada, pois esse tipo de consulta deseja criar a tabela como parte da execução.

  2. Em seguida, use o SSIS para exportar os resultados dessa tabela para .csv. O assistente de exportação do SSIS permite escolher seu delimitador etc. Isso é realmente útil para usar um | delimitador nas instâncias em que o conjunto de resultados contém vírgulas.

    Clique com o botão direito do mouse em DB Name > Tasks > Export Data

  3. Quando a exportação estiver concluída, execute o DROP TABLEcomando para limpar sua tabela de log.

    Drop Table dbo.LogTableName
Don Moehling
fonte
3
Oi Don. Eu adicionei alguma formatação à sua resposta. Você pode clicar em 'editar' no canto inferior esquerdo para ver o que mudou e clicar no bit "editado" xx minutos "para ver um histórico completo, se quiser reverter. Embora exequível, sua resposta não acrescenta muito mais o que já foi escrito e é improvável que atraem muita atenção.
Michael Green
0

Eu uso o MS Access DoCMD para exportar CSV do SQL Server. É capaz de fazê-lo com um único comando. O banco de dados de acesso é usado apenas para ativar o comando de acesso. Ele tem um bom desempenho e, como um benefício adicional (não sabe por que), cria um schema.ini para a tabela exportada.

Adão

CMD="SELECT * INTO [Text;HDR=Yes;DATABASE=C:\].[Results.txt]  
FROM [ODBC;DSN=SQL2017;Description=SQL2017;UID=.;Trusted_Connection=Yes;APP=Microsoft Office 2013;WSID=LAPTOP-XYZ;DATABASE=TempDB_DataDump_1].Results "

 Set appAccess = CreateObject("Access.Application") 
                appAccess.OpenCurrentDatabase "anyAccessdatabase.mdb" 
                   ' appAccess.DoCmd.SetWarnings 0
                    appAccess.DoCmd.runsql "CMD"
Adão
fonte
-1

Este procedimento irá gerar um arquivo CSV com a saída da consulta que você passa como parâmetro. O segundo parâmetro é o nome do seu arquivo CSV, certifique-se de passar o nome do arquivo com um caminho gravável válido.

Aqui está o script para criar o procedimento:

CREATE procedure [dbo].[usp_create_csv_file_from_query]
    @sql Nvarchar(MAX),
    @csvfile Nvarchar(200)
    as
    BEGIN
        if IsNull(@sql,'') = '' or IsNull(@csvfile,'') = ''
        begin
            RAISERROR ('Invalid SQL/CsvFile values passed!; Aborting...', 0, 1) WITH NOWAIT
            return
        end
        DROP TABLE if exists global_temp_CSVtable;
        declare 
            @columnList varchar(4000), 
            @columnList1 varchar(4000),
            @sqlcmd varchar(4000),
            @dos_cmd nvarchar(4000)

        set @sqlcmd = replace(@sql, 'from', 'into global_temp_CSVtable from')
        EXECUTE (@sqlcmd); 

        declare @cols table (i int identity, colname varchar(100))
        insert into @cols
        select column_name
        from information_schema.COLUMNS
        where TABLE_NAME = 'global_temp_CSVtable'

        declare @i int, @maxi int
        select @i = 1, @maxi = MAX(i) from @cols

        while(@i <= @maxi)
        begin
            select @sql = 'alter table global_temp_CSVtable alter column [' + colname + '] VARCHAR(max) NULL'
            from @cols
            where i = @i
            exec sp_executesql @sql
            select @i = @i + 1
        end

        SELECT 
             @columnList = COALESCE(@columnList + ''', ''', '') + column_name 
            ,@columnList1 = COALESCE(@columnList1 + ', ', '') + column_name
        from information_schema.columns
        where table_name =  'global_temp_CSVtable'
        ORDER BY ORDINAL_POSITION;

        SELECT @columnList = '''' + @columnList + '''';

        SELECT @dos_cmd='BCP "SELECT ' + @columnList + 
                        ' UNION ALL ' +
                        'SELECT * from ' + db_name() + '..global_temp_CSVtable" ' + 
                        'QUERYOUT ' + @csvfile + 
                        ' -c -t, -T'
        exec master.dbo.xp_cmdshell @dos_cmd, No_output 
        DROP TABLE if exists global_temp_CSVtable;
    end
Pareed Sharief
fonte
2
as respostas somente de código não são consideradas aceitáveis ​​aqui - você poderia adicionar algum comentário à sua resposta e por que ela funciona? (os comentários do código provavelmente ajudariam aqui também)
George.Palacios
Sim, e você também pode adicionar um exemplo de como usá-lo com sucesso?
Marcello Miorelli 28/09