Escribir el resultado seleccionado en un archivo csv

37

Necesitamos escribir los resultados de la consulta SELECT en un archivo csv. ¿Cómo se puede hacer usando T-SQL en SQL Server 2008 r2? Sé que se puede hacer en SSIS, pero por alguna razón, no tenemos esta opción.

Traté de usar el proceso sugerido en el artículo a continuación, pero cuando ejecuto el proceso, SQL se queja de que no puede ejecutar sys.sp_OACreate y sys.sp_OADestroy que se llaman en este proceso.

¿Sabes cómo podemos activar estos componentes o conoces una mejor manera de escribir en un archivo usando T-SQL?

Gracias por adelantado.

Cielo
fuente

Respuestas:

52

Usar la utilidad BCP

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

El -cargumento especifica la salida de caracteres c , en oposición al formato binario nativo de SQL; valores predeterminados esto a valores separados por tabuladores, pero -t ,cambia el campo t erminator a comas. -TEspecifica la autenticación de Windows ( " t conexión oxidado"), de lo contrario usar -U MyUserName -P MyPassword.

Esto no exporta encabezados de columna por defecto. Debe usar UNION ALL para los encabezados

O

Utilice SQLCMD

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

O

Use Powershell

Aquí hay un enlace a un artículo . Si termina usando esto, es posible que desee agregar -notypedespués Export-Csv $extractFilepara deshacerse de la columna innecesaria en el archivo de salida.

RK Kuppala
fuente
44
+1 Para la utilidad BCP: es muy fácil de usar, es la herramienta más rápida que he usado para exportar / importar información y hay muchas opciones. Le aconsejaré que agregue "> FileName.log" al final de la declaración; esto creará un archivo de registro.
gotqn
24

Además de la respuesta anterior, que le ayuda a automatizar la acción, si la necesita solo de vez en cuando puede hacerlo en Management Studio, simplemente haga clic derecho en el encabezado - Guardar resultados como -> elija un archivo .csv .

O si desea hacer eso para cada instrucción de selección que ejecute, puede cambiar la dirección de salida de los resultados a un archivo. Use Herramientas -> Opciones -> Resultados de la consulta - Resultados para archivar .

Otra forma, que se puede automatizar fácilmente y hace uso de SSIS, es mediante la función Exportar datos de Management Studio. Haga clic derecho en la base de datos -> Tareas -> Exportar datos. Hay un asistente con muchas opciones allí. Debe elegir la base de datos de origen, el destino y otras opciones. Para el destino, asegúrese de que sea "Archivo plano", explore y elija el tipo .csv, elija el formato que necesite y al final obtendrá un paquete SSIS que puede guardarse localmente y repetirse según sea necesario.

Mariana
fuente
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

Pero, hay un par de advertencias:

  1. Debe tener disponible el proveedor Microsoft.ACE.OLEDB.12.0. El proveedor de Jet 4.0 también funcionará, pero es antiguo, así que utilicé este en su lugar.
  2. El archivo .CSV ya debe existir. Si está utilizando encabezados (HDR = YES), asegúrese de que la primera línea del archivo .CSV sea una lista delimitada de todos los campos.
Slogmeister Extraordinaire
fuente
1
¡La mejor respuesta hasta ahora!
ajeh
1
gran trabajo incluyendo advertencias
JJS
5

Baja tecnología, pero ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
fuente
MySQL trata col1 + ',' + cast(col2 as varchar(10)) + ',' + col3como un nombre de columna e imprime NULL por todo el lugar.
Nikhil Wagh
4

Parece que ya tiene una solución aceptable, pero si tiene configurado el correo DB, podría hacer algo como esto:

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

Si de todas formas está enviando el archivo por correo electrónico en algún lugar, podría ahorrarle algunos pasos.

Shane Estelle
fuente
Justo lo que estaba buscando, felicitaciones a ti!
Mashchax
Aunque necesitará agregar el parámetro @profile_name si no tiene un perfil privado predeterminado para su usuario ni un perfil público para la base de datos.
Mashchax
1

Esto se puede hacer fácilmente en un proceso de 3 pasos:

  1. Escribe tu consulta como una SELECT INTOconsulta. Esto esencialmente exportará los resultados de su consulta a una tabla.

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

    Tenga en cuenta que esta tabla no puede existir cuando se ejecuta la consulta, ya que este tipo de consulta desea crear la tabla como parte de la ejecución.

  2. Luego use SSIS para exportar los resultados de esa tabla a .csv. El asistente de exportación SSIS le permite elegir su delimitador, etc. Esto es realmente útil para usar un | delimitador en casos donde el conjunto de resultados contiene comas.

    Haga clic derecho en DB Name > Tasks > Export Data

  3. Una vez que se complete la exportación, ejecute el DROP TABLEcomando para limpiar su tabla de registro.

    Drop Table dbo.LogTableName
Don Moehling
fuente
3
Hola don Agregué un poco de formato a su respuesta. Puede hacer clic en "editar" en la esquina inferior izquierda para ver qué ha cambiado y hacer clic en el bit "editado" xx minutos "para ver un historial completo si desea retroceder. Aunque es factible, su respuesta no agrega mucho más lo que ya se ha escrito y es poco probable que atraiga mucha atención.
Michael Green
0

Utilizo MS Access DoCMD para exportar CSV de SQL Server. Es capaz de hacerlo con un solo comando. La base de datos de acceso solo se usa para habilitar el comando de acceso. Funciona bien y, como beneficio adicional (no estoy seguro de por qué), crea un schema.ini para la tabla exportada.

Adán

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án
fuente
-1

Este procedimiento generará un archivo CSV con el resultado de la consulta que pase como parámetro. El segundo parámetro es su nombre de archivo CSV, asegúrese de pasar el nombre del archivo con una ruta de escritura válida.

Aquí está el script para crear el procedimiento:

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
Pena Pareed
fuente
2
las respuestas de solo código no se consideran aceptables aquí. ¿Podría agregar algún comentario sobre su respuesta y por qué funciona? (los comentarios de código probablemente también ayudarían aquí)
George.Palacios
Sí, ¿y también podría agregar un ejemplo de cómo lo usa con éxito?
Marcello Miorelli