Viết kết quả chọn vào tệp csv


37

Chúng ta cần ghi kết quả truy vấn CHỌN vào tệp csv. Làm thế nào có thể được thực hiện bằng T-SQL trong SQL Server 2008 r2? Tôi biết rằng nó có thể được thực hiện trong SSIS, nhưng vì một số lý do, chúng tôi không có tùy chọn này.

Tôi đã cố gắng sử dụng Proc được đề xuất trong bài viết dưới đây, nhưng khi tôi chạy Proc, SQL phàn nàn rằng không thể chạy sys.sp_OACreate và sys.sp_OADestroy được gọi trong Proc này.

Bạn có biết làm thế nào chúng ta có thể bật các thành phần này hoặc biết cách nào tốt hơn để ghi vào tệp bằng T-SQL không?

Cảm ơn trước.

Câu trả lời:


52

Sử dụng tiện ích BCP

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

Đối -csố chỉ định đầu ra c haracter, trái ngược với định dạng nhị phân nguyên gốc của SQL; mặc định này thành các giá trị được phân tách bằng tab, nhưng -t ,thay đổi trường t erminator thành dấu phẩy. -Tchỉ định xác thực Windows (" t rỉ kết nối"), nếu không sử dụng -U MyUserName -P MyPassword.

Điều này không xuất các tiêu đề cột theo mặc định. Bạn cần sử dụng UNION ALL cho các tiêu đề

HOẶC LÀ

Sử dụng SQLCMD

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

HOẶC LÀ

Sử dụng Powershell

Đây là một liên kết đến một bài viết . Nếu bạn kết thúc bằng cách sử dụng này, bạn có thể muốn nối thêm -notypesau Export-Csv $extractFileđể loại bỏ cột không cần thiết trên tệp đầu ra.


4
+1 Đối với tiện ích BCP - nó rất dễ sử dụng, nó là công cụ nhanh nhất mà tôi từng sử dụng để xuất / nhập thông tin và có rất nhiều tùy chọn. Tôi sẽ khuyên bạn nên thêm "> FileName.log" vào cuối câu lệnh - điều này sẽ tạo ra một tệp nhật ký.
gotqn

24

Thêm vào câu trả lời trước, giúp bạn tự động hóa hành động, nếu thỉnh thoảng bạn chỉ cần thực hiện nó trong Management Studio, chỉ cần nhấp chuột phải vào tiêu đề - Lưu kết quả dưới dạng -> chọn tệp .csv .

Hoặc nếu bạn muốn làm điều đó cho mỗi câu lệnh chọn mà bạn chạy, bạn có thể thay đổi hướng đầu ra của kết quả thành một tệp. Sử dụng Công cụ -> Tùy chọn -> Kết quả truy vấn - Kết quả để gửi .

Một cách khác, có thể được tự động hóa một cách dễ dàng và sử dụng SSIS, bằng cách sử dụng tính năng Xuất dữ liệu của Management Studio. Nhấp chuột phải vào cơ sở dữ liệu -> Nhiệm vụ -> Xuất dữ liệu. Có một thuật sĩ với rất nhiều lựa chọn ở đó. Bạn nên chọn cơ sở dữ liệu nguồn, đích và các tùy chọn khác. Đối với đích đến, hãy đảm bảo đó là "Tệp phẳng", duyệt và chọn loại .csv, chọn bất kỳ định dạng nào bạn cần và cuối cùng bạn sẽ có được gói SSIS có thể được lưu cục bộ và lặp lại theo yêu cầu.


10

Sử dụng 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

Nhưng, có một vài cảnh báo:

  1. Bạn cần phải có nhà cung cấp Microsoft.ACE.OLEDB.12.0. Nhà cung cấp Jet 4.0 cũng sẽ hoạt động, nhưng nó đã cũ, vì vậy tôi đã sử dụng cái này thay thế.
  2. Tệp .CSV sẽ phải tồn tại. Nếu bạn đang sử dụng các tiêu đề (HDR = CÓ), hãy đảm bảo dòng đầu tiên của tệp .CSV là danh sách được phân tách của tất cả các trường.

1
Câu trả lời tốt nhất cho đến nay!
ngày

1
công việc tuyệt vời bao gồm cả hãy cẩn thận
JJS

5

Công nghệ thấp, nhưng ...

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

MySQL xử lý col1 + ',' + cast(col2 as varchar(10)) + ',' + col3như một tên cột và in NULL ở mọi nơi.
Nikhil Wagh

4

Có vẻ như bạn đã có một giải pháp chấp nhận được, nhưng nếu bạn đã thiết lập thư db, bạn có khả năng có thể làm một cái gì đó như thế này:

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

Nếu bạn đang gửi email tệp ở đâu đó, nó có thể giúp bạn tiết kiệm một vài bước.


Chỉ là những gì tôi đang tìm kiếm, danh tiếng cho bạn!
Mashchax

Mặc dù bạn sẽ cần thêm tham số @profile_name nếu bạn không có hồ sơ riêng tư mặc định cho người dùng cũng như hồ sơ công khai cho cơ sở dữ liệu.
Mashchax

1

Điều này có thể dễ dàng được thực hiện trong một quy trình 3 bước:

  1. Viết truy vấn của bạn dưới dạng SELECT INTOtruy vấn. Điều này về cơ bản sẽ xuất kết quả truy vấn của bạn vào một bảng.

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

    Lưu ý, bảng này không thể tồn tại khi truy vấn chạy, vì loại truy vấn này muốn tạo bảng như một phần của thực thi.

  2. Sau đó sử dụng SSIS để xuất kết quả của bảng đó sang .csv. Trình hướng dẫn Xuất SSIS cho phép bạn chọn dấu phân cách, v.v ... Điều này thực sự tiện dụng khi sử dụng | dấu phân cách trong trường hợp tập kết quả chứa dấu phẩy.

    Nhấp chuột phải vào DB Name > Tasks > Export Data

  3. Khi quá trình xuất hoàn tất, hãy thực hiện DROP TABLElệnh để dọn sạch bảng nhật ký của bạn.

    Drop Table dbo.LogTableName

3
Giấu. Tôi đã thêm một số định dạng cho câu trả lời của bạn. Bạn có thể nhấp vào 'chỉnh sửa' ở phía dưới bên trái để xem những gì đã thay đổi và nhấp vào bit "xx phút" đã chỉnh sửa để xem toàn bộ lịch sử nếu bạn muốn quay lại. Mặc dù có thể, câu trả lời của bạn không thêm nhiều những gì đã được viết và không có khả năng thu hút nhiều sự chú ý.
Michael Green

0

Tôi sử dụng MS Access DoCMD để xuất CSV từ SQL Server. Nó có thể làm điều đó với một lệnh duy nhất. Cơ sở dữ liệu truy cập chỉ được sử dụng để kích hoạt lệnh truy cập. Nó hoạt động tốt và như là một lợi ích bổ sung (không chắc tại sao) nó tạo ra một lược đồ.ini cho bảng được xuất.

Ađam

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

Quy trình này sẽ tạo tệp CSV với đầu ra của truy vấn bạn chuyển dưới dạng tham số. Tham số thứ 2 là tên tệp CSV của bạn, đảm bảo bạn chuyển tên tệp với đường dẫn có thể ghi hợp lệ.

Đây là kịch bản để tạo thủ tục:

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
mã chỉ các câu trả lời không được xem là chấp nhận được ở đây - bạn có thể thêm một số nhận xét về câu trả lời của mình không và tại sao nó lại hoạt động? (nhận xét mã có thể cũng sẽ giúp ở đây)
George.Palacios

Có, và bạn cũng có thể thêm một ví dụ như cách bạn sử dụng thành công không?
Marcello Miorelli
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.