Запис результату вибору у файл 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 ,змінює поле t erminator на коми. -Tвизначає автентифікацію Windows (" t іржаве з'єднання"), в іншому випадку використовуйте -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" в кінці заяви - це створить файл журналу.
gotqn

24

Додавши до попередньої відповіді, яка допомагає вам автоматизувати дії, якщо вам це потрібно лише час від часу, ви можете робити це в студії управління, просто клацніть правою кнопкою миші на заголовку - Зберегти результати як -> виберіть файл .csv .

Або якщо ви хочете зробити це для кожного запущеного оператора select, ви можете змінити напрямок виводу результатів у файл. Використовуйте Інструменти -> Параметри -> Результати запиту - Результати для файлу .

Інший спосіб, який може бути легко автоматизований і використовує SSIS, це за допомогою функції експорту даних Data Studio Management. Клацніть правою кнопкою миші на базі даних -> Завдання -> Експорт даних. Там є майстер з великою кількістю опцій. Вам слід вибрати джерельну базу даних, пункт призначення та інші параметри. Переконайтеся, що це "Плоский файл", перегляньте та оберіть тип .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 = ТАК), переконайтеся, що перший рядок .CSV-файлу - це розділений список усіх полів.

1
Найкраща відповідь поки!
ajeh

1
чудова робота, включаючи застереження
JJS

5

Низькі технології, але ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;

MySQL розглядає col1 + ',' + cast(col2 as varchar(10)) + ',' + col3як ім'я стовпця та друкує NULL у всьому місці.
Nikhil Wagh

4

Схоже, у вас вже є прийнятне рішення, але якщо у вас налаштована db-пошта, ви потенційно можете зробити щось подібне:

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

2
Відповіді лише на код тут не сприймаються як прийнятні - ви можете додати коментар до своєї відповіді і чому це працює? (коментарі до коду, ймовірно, допоможуть і тут)
George.Palacios

Так, і чи можете ви також додати приклад того, як ви успішно його використовуєте?
Марчелло Міореллі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.