将选择结果写入CSV文件


37

我们需要将SELECT查询结果写入一个csv文件。如何在SQL Server 2008 r2中使用T-SQL完成?我知道可以在SSIS中完成,但是由于某些原因,我们没有此选项。

我尝试在下面的文章中使用建议的proc,但是当我运行proc时,SQL抱怨无法运行在此proc中调用的sys.sp_OACreate和sys.sp_OADestroy。

您知道我们如何打开这些组件,或者知道使用T-SQL写入文件的更好方法吗?

提前致谢。

Answers:


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”-这将创建一个日志文件。
gotqn 2012年

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;

MySQL视为col1 + ',' + cast(col2 as varchar(10)) + ',' + col3列名,并在所有位置打印NULL。
Nikhil Wagh

4

看来您已经有了一个可以接受的解决方案,但是如果您设置了数据库邮件,则可以执行以下操作:

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从SQL Server导出CSV。它可以用一个命令来完成。access数据库仅用于启用access命令。它表现良好,并且有一个额外的好处(不确定为什么),它为导出的表创建了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

是的,您还可以添加一个示例以成功使用它吗?
Marcello Miorelli
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.