使用bcp实用程序和SQL Server 2008将表导出到具有列标题(列名称)的文件

JD *_*ong 35 sql-server csv bcp header

我已经看到一些hacks试图让bcp实用程序导出列名和数据.如果我所做的只是将表转储到文本文件中,那么使用bcp添加列标题的最简单的方法是什么?

这是我目前使用的bcp命令:

bcp myschema.dbo.myTableout myTable.csv /SmyServer01 /c /t, -T
Run Code Online (Sandbox Code Playgroud)

Dyl*_*ogg 45

此方法使用BCP自动使用行数据输出列名称.

该脚本为列标题写入一个文件(从INFORMATION_SCHEMA.COLUMNS表中读取),然后使用表数据附加另一个文件.

最终输出结合在一起TableData.csv,其中包含标题和行数据.只需替换顶部的环境变量即可指定服务器,数据库和表名称.

set BCP_EXPORT_SERVER=put_my_server_name_here
set BCP_EXPORT_DB=put_my_db_name_here
set BCP_EXPORT_TABLE=put_my_table_name_here

BCP "DECLARE @colnames VARCHAR(max);SELECT @colnames = COALESCE(@colnames + ',', '') + column_name from %BCP_EXPORT_DB%.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='%BCP_EXPORT_TABLE%'; select @colnames;" queryout HeadersOnly.csv -c -T -S%BCP_EXPORT_SERVER%

BCP %BCP_EXPORT_DB%.dbo.%BCP_EXPORT_TABLE% out TableDataWithoutHeaders.csv -c -t, -T -S%BCP_EXPORT_SERVER%

set BCP_EXPORT_SERVER=
set BCP_EXPORT_DB=
set BCP_EXPORT_TABLE=

copy /b HeadersOnly.csv+TableDataWithoutHeaders.csv TableData.csv

del HeadersOnly.csv
del TableDataWithoutHeaders.csv
Run Code Online (Sandbox Code Playgroud)

请注意,如果需要提供凭据,请将-T选项替换为-U my_username -P my_password

此方法的优点是始终使列名与表同步INFORMATION_SCHEMA.COLUMNS.缺点是它会创建临时文件.微软应该真正修复bcp实用程序来支持它.

该解决方案采用从SQL行级联伎俩在这里与BCP理念相结合,从这里

  • 很棒的脚本哥们。如果可以的话,我会投票两次。有什么方法可以将表和数据库的名称作为批处理脚本变量? (2认同)

Fil*_*Vos 42

最简单的方法是使用该queryout选项并使用union all链接列列表与实际表格内容

    bcp "select 'col1', 'col2',... union all select * from myschema.dbo.myTableout" queryout myTable.csv /SmyServer01 /c /t, -T
Run Code Online (Sandbox Code Playgroud)

一个例子:

create table Question1355876 
(id int, name varchar(10), someinfo numeric)

insert into Question1355876 
values (1, 'a', 123.12)
     , (2, 'b', 456.78)
     , (3, 'c', 901.12)
     , (4, 'd', 353.76)
Run Code Online (Sandbox Code Playgroud)

此查询将返回标题为第一行的信息.(注意数值的强制转换)

select 'col1', 'col2', 'col3'
union all
select cast(id as varchar(10)), name, cast(someinfo as varchar(28))
from Question1355876
Run Code Online (Sandbox Code Playgroud)

bcp命令将是:

bcp "select 'col1', 'col2', 'col3' union all select cast(id as varchar(10)), name, cast(someinfo as varchar(28)) from Question1355876" queryout myTable.csv /SmyServer01 /c /t, -T
Run Code Online (Sandbox Code Playgroud)

  • 引发错误:将 varchar 值“COL001”转换为数据类型 int 时转换失败。 (2认同)
  • 我添加了一个包含数值的示例.您需要将数字列转换为varchar(或nvarchar) (2认同)
  • Order By子句失败! (2认同)

Con*_*ngo 16

为了:

  • 视窗,64 位
  • SQL Server(使用SQL Server 2017测试,它应该适用于所有版本):

选项 1:命令提示符

sqlcmd -s, -W -Q "set nocount on; select * from [DATABASE].[dbo].[TABLENAME]" | findstr /v /c:"-" /b > "c:\dirname\file.csv"
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • [DATABASE].[dbo].[TABLENAME] 是要写的表。
  • c:\dirname\file.csv 是要写入的文件(用引号括起来以处理带空格的路径)。
  • 输出 .csv 文件包括标题。

注意:我倾向于避免bcp:它是遗留的,它早于sqlcmd十年,而且它似乎永远不会在不引起一大堆头痛的情况下工作。

选项 2:在 SQL 脚本中

-- Export table [DATABASE].[dbo].[TABLENAME] to .csv file c:\dirname\file.csv
exec master..xp_cmdshell 'sqlcmd -s, -W -Q "set nocount on; select * from [DATABASE].[dbo].[TABLENAME]" | findstr /v /c:"-" /b > "c:\dirname\file.csv"'
Run Code Online (Sandbox Code Playgroud)

疑难解答:必须在 MSSQL 中启用 xp_cmdshell

样本输出

文件file.csv::

ID,Name,Height
1,Bob,192
2,Jane,184
3,Harry,186
Run Code Online (Sandbox Code Playgroud)

速度

理论上尽可能快:与bcp从 SSMS 手动导出的速度相同,并且比手动导出快许多倍。

参数说明(可选 - 可以忽略)

sqlcmd

  • -s, 在每列之间放置一个逗号。
  • -W 消除填充值的任一侧。
  • set nocount on 消除了查询末尾的垃圾行。

对于findstr

  • 所有这些都是删除标题下方的第二行下划线,例如--- ----- ---- ---- ----- --.
  • /v /c:"-" 匹配任何以“-”开头的行。
  • /b 返回所有其他行。

导入其他程序

在 Excel 中:

  • 可以直接在Excel中打开文件。

在 Python 中:

import pandas as pd
df_raw = pd.read_csv("c:\dirname\file.csv")
Run Code Online (Sandbox Code Playgroud)

  • 这很棒。我特别喜欢用一行 SQL 来运行导出。我可能会开始使用它而不是 bcp。唯一需要注意的是,如果第 1 列中的任何值以“-”开头,它们将从导出中删除。负数转换为 varchar 可能会变得混乱。 (3认同)

Alc*_*att 10

一个很好的选择是SqlCmd,因为它确实包含头文件,但它的缺点是在数据周围添加空间填充以便人类可读.您可以将SqlCmd与GnuWin32 sed(流编辑)实用程序结合使用以清除结果.这是一个对我有用的例子,虽然我不能保证它是防弹的.

首先,导出数据:

sqlcmd -S Server -i C:\Temp\Query.sql -o C:\Temp\Results.txt -s"    "
Run Code Online (Sandbox Code Playgroud)

-s" "是双引号中的制表符.我发现您必须通过批处理文件运行此命令,否则Windows命令提示符会将该选项卡视为自动完成命令,并将替换文件名代替选项卡.

如果Query.sql包含:

SELECT name, object_id, type_desc, create_date
FROM MSDB.sys.views
WHERE name LIKE 'sysmail%'
Run Code Online (Sandbox Code Playgroud)

然后你会在Results.txt中看到类似的东西

name                                          object_id   type_desc           create_date            
-------------------------------------------   ----------- ------------------- -----------------------
sysmail_allitems                               2001442204 VIEW                2012-07-20 17:38:27.820
sysmail_sentitems                              2017442261 VIEW                2012-07-20 17:38:27.837
sysmail_unsentitems                            2033442318 VIEW                2012-07-20 17:38:27.850
sysmail_faileditems                            2049442375 VIEW                2012-07-20 17:38:27.860
sysmail_mailattachments                        2097442546 VIEW                2012-07-20 17:38:27.933
sysmail_event_log                              2129442660 VIEW                2012-07-20 17:38:28.040

(6 rows affected)
Run Code Online (Sandbox Code Playgroud)

接下来,使用sed解析文本:

sed -r "s/ +\t/\t/g" C:\Temp\Results.txt | sed -r "s/\t +/\t/g" | sed -r "s/(^ +| +$)//g" | sed 2d | sed $d | sed "/^$/d" > C:\Temp\Results_New.txt
Run Code Online (Sandbox Code Playgroud)

请注意,该2d命令表示删除第二行,该$d命令表示删除最后一行,并"/^$/d"删除任何空行.

清理后的文件看起来像这样(虽然我更换了标签,|因此可以在这里看到它们):

name|object_id|type_desc|create_date
sysmail_allitems|2001442204|VIEW|2012-07-20 17:38:27.820
sysmail_sentitems|2017442261|VIEW|2012-07-20 17:38:27.837
sysmail_unsentitems|2033442318|VIEW|2012-07-20 17:38:27.850
sysmail_faileditems|2049442375|VIEW|2012-07-20 17:38:27.860
sysmail_mailattachments|2097442546|VIEW|2012-07-20 17:38:27.933
sysmail_event_log|2129442660|VIEW|2012-07-20 17:38:28.040
Run Code Online (Sandbox Code Playgroud)


Mys*_*i0n 6

我最近想知道如何做到这一点,虽然我喜欢顶部最流行的解决方案,但它根本不适用于我,因为我需要将名称作为我在脚本中输入的别名,所以我使用了一些批处理文件(在同事的帮助下)完成自定义表名.

启动bcp的批处理文件在脚本底部有一行代码,该代码执行另一个脚本,该脚本将模板文件与头名称和使用下面的代码使用bcp导出的文件合并.希望这可以帮助处于我的情况中的其他人.

echo Add headers from template file to exported sql files....
Echo School 0031
copy e:\genin\templates\TEMPLATE_Courses.csv + e:\genin\0031\courses0031.csv e:\genin\finished\courses0031.csv /b
Run Code Online (Sandbox Code Playgroud)


小智 6

我遇到了同样的问题。我需要使用 SQL Server bcp 实用程序导出列标题。通过这种方式,我一次性将带有数据的表“标题”导出到同一个导出文件中。

声明@table_name VARCHAR(50) ='mytable'
声明 @columnHeader VARCHAR(8000)
SELECT @columnHeader = COALESCE(@columnHeader+',' ,'')+ ''''+column_name +'''' FROM Nal2013.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=@table_name
SELECT @raw_sql = 'bcp "SELECT '+ @columnHeader +' UNION ALL SELECT * FROM mytable" queryout c:\datafile.csv -c -t, -T -S '+ @@servername
EXEC xp_cmdshell @raw_sql

快乐编码:)