Запись результата выбора в CSV-файл

37

Нам нужно записать результаты запроса SELECT в CSV-файл. Как это можно сделать с помощью T-SQL в SQL Server 2008 r2? Я знаю, что это можно сделать в SSIS, но по некоторым причинам у нас нет этой опции.

Я попытался использовать предложенный proc в статье ниже, но когда я запускаю proc, SQL жалуется, что не может запустить sys.sp_OACreate и sys.sp_OADestroy, которые вызываются в этом proc.

Знаете ли вы, как мы можем включить эти компоненты, или знаете какой-нибудь лучший способ записи в файл с использованием T-SQL?

Заранее спасибо.

Небо
источник

Ответы:

52

Используйте утилиту BCP

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

В -cаргумент определяет гр haracter производства, в отличие от родного двоичного формата в SQL; это по умолчанию значения , разделенные табуляцией, но -t ,изменяет поле т erminator к запятой. -TАутентификация определяет для Windows ( « т проржавели соединение»), в противном случае использовать -U MyUserName -P MyPassword.

По умолчанию заголовки столбцов не экспортируются. Вам нужно использовать UNION ALL для заголовков

ИЛИ

Используйте SQLCMD

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

ИЛИ

Используйте Powershell

Вот ссылка на статью . Если вы в конечном итоге используете это, вы можете добавить -notypeпосле, Export-Csv $extractFileчтобы избавиться от ненужного столбца в выходном файле.

РК Куппала
источник
4
+1 Для утилиты BCP - она ​​очень проста в использовании, это самый быстрый инструмент, который я когда-либо использовал для экспорта / импорта информации, и есть много вариантов. Я посоветую вам добавить «> FileName.log» в конце оператора - это создаст файл журнала.
получил
24

В добавление к предыдущему ответу, который помогает автоматизировать действие, если вы нуждаетесь в нем только время от времени, вы можете сделать это в Management Studio, просто щелкните правой кнопкой мыши заголовок - Сохранить результаты как -> выберите файл .csv .

Или, если вы хотите сделать это для каждого оператора select, который вы выполняете, вы можете изменить направление вывода результатов на файл. Используйте Сервис -> Параметры -> Результаты запроса - Результаты в файл .

Другой способ, который может быть легко автоматизирован и использует SSIS, заключается в использовании функции экспорта данных в Management Studio. Щелкните правой кнопкой мыши базу данных -> Задачи -> Экспорт данных. Там есть мастер с множеством вариантов. Вы должны выбрать исходную базу данных, пункт назначения и другие параметры. Для пункта назначения убедитесь, что это «Плоский файл», найдите и выберите тип .csv, выберите любой необходимый формат, и в конце вы получите пакет служб SSIS, который можно сохранить локально и повторить при необходимости.

Мэриан
источник
10

Используйте 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

Но есть несколько предостережений:

  1. У вас должен быть доступный поставщик Microsoft.ACE.OLEDB.12.0. Поставщик Jet 4.0 тоже будет работать, но он древний, поэтому я использовал этот.
  2. Файл .CSV должен уже существовать. Если вы используете заголовки (HDR = YES), убедитесь, что первая строка файла .CSV представляет собой список всех полей с разделителями.
Слогмейстер экстраординарный
источник
1
Лучший ответ на данный момент!
ajeh
1
отличная работа, включая предупреждения
JJS
5

Низкая технология, но ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
источник
MySQL обрабатывает col1 + ',' + cast(col2 as varchar(10)) + ',' + col3как имя столбца и печатает NULL повсюду.
Нихил Ваг
4

Похоже, у вас уже есть приемлемое решение, но если вы настроили db mail, вы могли бы сделать что-то вроде этого:

EXEC msdb.dbo.sp_send_dbmail
    @recipients='your.email@domain.com',
    @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

Если вы отправляете файл куда-нибудь по электронной почте, это может сэкономить вам несколько шагов.

Шейн Эстель
источник
Именно то, что я искал, слава тебе!
Mashchax
Хотя вам нужно будет добавить параметр @profile_name, если у вас нет личного профиля по умолчанию для вашего пользователя или общедоступного профиля для базы данных.
Mashchax
1

Это легко сделать в 3 этапа:

  1. Напишите ваш запрос как SELECT INTOзапрос. Это по существу экспортирует результаты вашего запроса в таблицу.

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

    Обратите внимание, эта таблица не может существовать при выполнении запроса, так как этот тип запроса хочет создать таблицу как часть выполнения.

  2. Затем используйте SSIS для экспорта результатов этой таблицы в .csv. Мастер экспорта служб SSIS позволяет выбрать разделитель и т. Д. Это действительно удобно для использования | разделитель в тех случаях, когда результирующий набор содержит запятые.

    Щелкните правой кнопкой мыши на DB Name > Tasks > Export Data

  3. После завершения экспорта выполните DROP TABLEкоманду для очистки таблицы журнала.

    Drop Table dbo.LogTableName
Дон Мёлинг
источник
3
Привет дон Я добавил форматирование в ваш ответ. Вы можете нажать «изменить» в левом нижнем углу, чтобы увидеть, что изменилось, и нажать «отредактированный» xx минут », чтобы увидеть полную историю, если вы хотите откатиться. Хотя и выполнимо, ваш ответ не добавляет много то, что уже было написано и вряд ли привлечет много внимания.
Майкл Грин
0

Я использую MS Access DoCMD для экспорта CSV из SQL Server. Это можно сделать с помощью одной команды. База данных доступа используется только для включения команды доступа. Он работает хорошо, и в качестве дополнительного преимущества (не уверен почему) он создает schema.ini для экспортируемой таблицы.

Адам

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"
Адам
источник
-1

Эта процедура создаст файл CSV с выводом запроса, который вы передадите в качестве параметра. Второй параметр - это имя файла CSV, убедитесь, что вы передаете имя файла с допустимым путем записи.

Вот скрипт для создания процедуры:

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
источник
2
Ответы с кодом только здесь не рассматриваются как приемлемые - не могли бы вы добавить комментарий к своему ответу и почему он работает? (комментарии кода, вероятно, также помогут здесь)
George.Palacios
Да, и не могли бы вы также добавить пример того, как вы успешно его используете?
Марчелло Миорелли