https://www.cnblogs.com/downmoon/archive/2012/05/04/2482995.html

 

SQL Server 2008中SQL应用系列及BI学习笔记系列--目录索引

前几天在项目中遇到一个问题,需要从SQL Server导出表到Excel,但需要带列名。晚上尝试了几种方法,并作个小结。

假定表如下:

  1. USE testDb2
  2. GO
  3. IF NOT OBJECT_ID('Demo_A') IS NULL
  4. DROP TABLE [Demo_A]
  5.  
  6. /****** Object: Table [dbo].[Demo_A] downmoon:3w@live.cn ******/
  7. CREATE TABLE [dbo].[Demo_A](
  8. [ID] int not null,
  9. [Name] [Nvarchar](20) NOT NULL
  10. )
  11. GO
  12. INSERT [dbo].[Demo_A]
  13. SELECT 1,'郭靖'
  14. union ALL SELECT 2,'胡一刀'
  15. union ALL SELECT 3,'令狐冲'
  16. GO

如果通常的思路,我们可以用BCP,命令如下:

  1. -- To allow advanced options to be changed.
  2. EXEC sp_configure 'show advanced options', 1
  3. GO
  4. -- To update the currently configured value for advanced options.
  5. RECONFIGURE
  6. GO
  7. -- To enable the feature.
  8. EXEC sp_configure 'xp_cmdshell', 1
  9. GO
  10. -- To update the currently configured value for this feature.
  11. RECONFIGURE
  12. GO
  13.  
  14. EXEC master..xp_cmdshell 'bcp Testdb2.dbo.Demo_A out c:\Temp.xls -c -q -S"ap4\Net2012" -U"sa" -P"sA"'

这样得到的xls文件中,Sheet是不带列名的。但可以改进一下,得到如下命令(参考:http://social.msdn.microsoft.com/forums/en-US/sqlgetstarted/thread/812b8eec-5b77-42a2-bd23-965558ece5b9/):

 

方法一:使用BCP

为了方便,我创建了一个存储过程:

  1. /****** SQL Export to xls ***************/
  2. /* Example */
  3. /*CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExxelWithHeader.xls'*/
  4. /* 2012.5.4 BY tony,邀月, 3w@live.cn */
  5. ---- CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls'
  6.  
  7. Create Procedure CPP_Export_To_Excel_With_Header
  8. (
  9. @db_name varchar(255),
  10. @table_name varchar(255),
  11. @file_path varchar(255)
  12. )
  13. as
  14.  
  15. ----Generate column names as a recordset
  16. declare @columns varchar(8000), @sql varchar(8000)
  17. declare @HeadersOnlyFile varchar(255),@TableDataWithoutHeaders varchar(255)
  18. set @HeadersOnlyFile=replace(cast(newid() as VARCHAR(40)),'-','')+'1.xls'
  19.  
  20. set @TableDataWithoutHeaders=replace(cast(newid() as VARCHAR(40)),'-','')+'2.xls'
  21. select
  22. @columns=coalesce(@columns+',','')+column_name+' as '+column_name
  23. from
  24. information_schema.columns
  25. where
  26. table_name=@table_name
  27. select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''')
  28. print @columns
  29. ----Generate column names file
  30. set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@HeadersOnlyFile+'" -c'''
  31. print @sql
  32. exec(@sql)
  33.  
  34. ----Create a dummy file to have actual data
  35. set @sql='exec master..xp_cmdshell ''bcp "'+@db_name+'.dbo.'+@table_name+'" out "'+@TableDataWithoutHeaders+'" -c -t -T'''
  36. print @sql
  37. exec(@sql)
  38.  
  39. --Merge File into One Final Format
  40. set @sql='exec master..xp_cmdshell ''copy /b '+@HeadersOnlyFile+'+'+@TableDataWithoutHeaders+' '+@file_path+''''
  41. print @sql
  42. exec(@sql)
  43.  
  44. --Delete temp File
  45. set @sql='exec master..xp_cmdshell ''del '+@HeadersOnlyFile+''''
  46. exec(@sql)
  47. set @sql='exec master..xp_cmdshell ''del '+@TableDataWithoutHeaders+''''
  48. exec(@sql)

调用方法:

  1. CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls'

另外有类似的处理方法:(看这里:http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49926),其主要思路如下:

 

方法二:

  1. create procedure proc_generate_excel_with_columns
  2. (
  3. @db_name varchar(100),
  4. @table_name varchar(100),
  5. @file_name varchar(100)
  6. )
  7. as
  8.  
  9. --Generate column names as a recordset
  10. declare @columns varchar(8000), @sql varchar(8000), @data_file varchar(100)
  11. select
  12. @columns=coalesce(@columns+',','')+column_name+' as '+column_name
  13. from
  14. information_schema.columns
  15. where
  16. table_name=@table_name
  17. select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''')
  18.  
  19. --Create a dummy file to have actual data
  20. select @data_file=substring(@file_name,1,len(@file_name)-charindex('\',reverse(@file_name)))+'\data_file.xls'
  21.  
  22. --Generate column names in the passed EXCEL file
  23. set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@file_name+'" -c'''
  24. exec(@sql)
  25.  
  26. --Generate data in the dummy file
  27. set @sql='exec master..xp_cmdshell ''bcp "select * from '+@db_name+'..'+@table_name+'" queryout "'+@data_file+'" -c'''
  28. exec(@sql)
  29.  
  30. --Copy dummy file to passed EXCEL file
  31. set @sql= 'exec master..xp_cmdshell ''type '+@data_file+' >> "'+@file_name+'"'''
  32. exec(@sql)
  33.  
  34. --Delete dummy file
  35. set @sql= 'exec master..xp_cmdshell ''del '+@data_file+''''
  36. exec(@sql)

调用示例:

  1. EXEC proc_generate_excel_with_columns 'your dbname', 'your table name','your file path'

如果,你的环境是SQL Server 2005,那么可以有:

 

方法三,使用sp_makewebtask,仅适用于SQL Server 2005

  1. 0)表T1结构
  2. a int
  3. b int
  4. x char
  5.  
  6. 1)开启Web Assistant Procedures
  7.  
  8. exec sp_configure 'show advanced options', 1
  9. RECONFIGURE
  10. exec sp_configure 'Web Assistant Procedures', 1
  11. RECONFIGURE
  12.  
  13. 2)执行如下语句
  14.  
  15. EXEC sp_makewebtask
  16. @outputfile = 'd:\testing.xls',
  17. @query = 'Select TOP 10 * from shenliang1985..T1',
  18. @colheaders =1,
  19. @FixedFont=0,@lastupdated=0,@resultstitle='Querying details'
  20.  
  21. 3)查看生成的EXCEl
  22.  
  23. Querying details
  24.  
  25. Last updated: 2010-03-03 01:02:59.263
  26.  
  27. a b x
  28. 0 0 0
  29. 2 5 1
  30. 4 10 2
  31. 6 15 3
  32. 8 20 4
  33. 10 25 5
  34. 12 30 6
  35. 14 35 7
  36. 16 40 8
  37. 18 45 9

可惜SQL Server 2008以后sp_makewebtask 这个存储过程取消了,后续版本也不再启用。
方法一和方法二其实生成的文件都不上真正的Excel文件,虽然后缀名为xls,为此,找到邹建写的一个存储过程。

 

方法四,使用OpenRowSet:

  1. /*--数据导出EXCEL
  2.  
  3. 导出查询中的数据到Excel,包含字段名,文件为真正的Excel文件
  4. 如果文件不存在,将自动创建文件
  5. 如果表不存在,将自动创建表
  6. 基于通用性考虑,仅支持导出标准数据类型
  7.  
  8. --邹建 2003.10(引用请保留此信息)--*/
  9.  
  10. /*--调用示例
  11.  
  12. p_exporttb @sqlstr='select * from 地区资料'
  13. ,@path='c:\',@fname='aa.xls',@sheetname='地区资料'
  14. --*/
  15. create proc p_exporttb
  16. @sqlstr varchar(8000),--查询语句,如果查询语句中使用了order by ,请加上top 100 percent
  17. @path nvarchar(1000),--文件存放目录
  18. @fname nvarchar(250),--文件名
  19. @sheetname varchar(250)=''--要创建的工作表名,默认为文件名
  20. as
  21. declare @err int,@src nvarchar(255),@desc nvarchar(255),@out int
  22. declare @obj int,@constr nvarchar(1000),@sql varchar(8000),@fdlist varchar(8000)
  23.  
  24. --参数检测
  25. if isnull(@fname,'')=''set @fname='temp2012.xls'
  26. if isnull(@sheetname,'')='' set @sheetname=replace(@fname,'.','#')
  27.  
  28. --检查文件是否已经存在
  29. if right(@path,1)<>'\' set @path=@path+'\'
  30. create table #tb(a bit,b bit,c bit)
  31. set @sql=@path+@fname
  32. insert into #tb exec master..xp_fileexist @sql
  33.  
  34. --数据库创建语句
  35. set @sql=@path+@fname
  36. if exists(select 1 from #tb where a=1)
  37. set @constr='DRIVER={Microsoft Excel Driver (*.xls)};DSN='''';READONLY=FALSE'
  38. +';CREATE_DB="'+@sql+'";DBQ='+@sql
  39. else
  40. set @constr='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties="Excel 8.0;HDR=YES'
  41. +';DATABASE='+@sql+'"'
  42.  
  43. --连接数据库
  44. exec @err=sp_oacreate 'adodb.connection',@obj out
  45. if @err<>0 goto lberr
  46.  
  47. exec @err=sp_oamethod @obj,'open',null,@constr
  48. if @err<>0 goto lberr
  49.  
  50. --创建表的SQL
  51. declare @tbname sysname
  52. set @tbname='##tmp_'+convert(varchar(38),newid())
  53. set @sql='select * into ['+@tbname+'] from('+@sqlstr+') a'
  54. exec(@sql)
  55.  
  56. select @sql='',@fdlist=''
  57. select @fdlist=@fdlist+',['+a.name+']'
  58. ,@sql=@sql+',['+a.name+'] '
  59. +case
  60. when b.name like '%char'
  61. then case when a.length>255 then 'memo'
  62. else 'text('+cast(a.length as varchar)+')' end
  63. when b.name like '%int' or b.name='bit' then 'int'
  64. when b.name like '%datetime' then 'datetime'
  65. when b.name like '%money' then 'money'
  66. when b.name like '%text' then 'memo'
  67. else b.name end
  68. FROM tempdb..syscolumns a left join tempdb..systypes b on a.xtype=b.xusertype
  69. where b.name not in('image','uniqueidentifier','sql_variant','varbinary','binary','timestamp')
  70. and a.id=(select id from tempdb..sysobjects where name=@tbname)
  71.  
  72. if @@rowcount=0 return
  73.  
  74. select @sql='create table ['+@sheetname
  75. +']('+substring(@sql,2,8000)+')'
  76. ,@fdlist=substring(@fdlist,2,8000)
  77.  
  78. exec @err=sp_oamethod @obj,'execute',@out out,@sql
  79. if @err<>0 goto lberr
  80.  
  81. exec @err=sp_oadestroy @obj
  82.  
  83. --导入数据
  84. set @sql='openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=YES
  85. ;DATABASE='+@path+@fname+''',['+@sheetname+'$])'
  86.  
  87. exec('insert into '+@sql+'('+@fdlist+') select '+@fdlist+' from ['+@tbname+']')
  88.  
  89. set @sql='drop table ['+@tbname+']'
  90. exec(@sql)
  91. return
  92.  
  93. lberr:
  94. exec sp_oageterrorinfo 0,@src out,@desc out
  95. lbexit:
  96. select cast(@err as varbinary(4)) as 错误号
  97. ,@src as 错误源,@desc as 错误描述
  98. select @sql,@constr,@fdlist
  99. go

为了执行这个存储过程,你得先打开以下开关:

  1. -- To allow advanced options to be changed.
  2. EXEC sp_configure 'show advanced options', 1
  3. GO
  4. -- To allow advanced options to be changed.
  5. EXEC sp_configure 'Ole Automation Procedures', 1
  6. GO
  7.  
  8. EXEC sp_configure 'Ad Hoc Distributed Queries', 1
  9. GO
  10.  
  11. -- To update the currently configured value for advanced options.
  12. RECONFIGURE
  13. GO

调用示例:

  1. p_exporttb @sqlstr='select * from [Demo_A]'
  2. ,@path='c:\',@fname='Export2xls_ByProc.xls',@sheetname='员工名称'

结果确实是正宗的xls文件。

如果你是兼写程序的DBA,那么NPOI是你理想的选择,因为它是纯原生的不依赖于Office组件的开源第三方组件,它提供了一个“CreateExportDataTableSheetAndHeaderRow”方法可以让你方便的生成纯正的Excel,遗憾的是,目前好像只支持到Excel 2003。示例请看这儿(http://scottonwriting.net/sowblog/archive/2011/06/08/export-an-ado-net-datatable-to-excel-using-npoi.aspx),该组件的源码:http://npoi.codeplex.com/

 

方法五:

  1. protected Sheet CreateExportDataTableSheetAndHeaderRow(DataTable exportData, string sheetName, CellStyle headerRowStyle)
  2. {
  3. var sheet = this.Workbook.CreateSheet(EscapeSheetName(sheetName));
  4.  
  5. // Create the header row
  6. var row = sheet.CreateRow(0);
  7.  
  8. for (var colIndex = 0; colIndex < exportData.Columns.Count; colIndex++)
  9. {
  10. var cell = row.CreateCell(colIndex);
  11. cell.SetCellValue(exportData.Columns[colIndex].ColumnName);
  12.  
  13. if (headerRowStyle != null)
  14. cell.CellStyle = headerRowStyle;
  15. }
  16.  
  17. return sheet;
  18. }

当然,如果你觉得以上方法门槛有点高,那么SSIS可能是你的首选,它的优势在于简单直观,并且可以导出为Excel2007格式。

只要在导出时选择第一行包含列名,即可。

 

方法六,使用SSIS

因为有人觉得界面过于繁琐,于是仿照导出向导的思路写了一个批处理,你可以修改为自己适合的内容:

 

方法七:(http://social.msdn.microsoft.com/forums/en-US/sqlgetstarted/thread/812b8eec-5b77-42a2-bd23-965558ece5b9/)

  1. @ECHO OFF
  2. REM -------------------------------------------------------------------------------
  3. REM Generic script for exporting data to file from SQL Server using a SQL query.
  4. REM The resulting file will be tab separated with newline as the row delimiter.
  5. REM A log file is generated and kept in case of an error or when in debug mode.
  6. REM See command syntax for details.
  7. REM
  8. REM History:
  9. REM 20120327 Lars Rönnbäck CREATED
  10. REM -------------------------------------------------------------------------------
  11. :constants
  12. SET myCodePage=ACP
  13. :variables
  14. SET theQuery=%~1
  15. SET theFile=%~2
  16. SET theServer=%~3
  17. SET theDebug=%~4
  18. SET /a aRandomNumber=%random%%%1000
  19. FOR /F "usebackq tokens=1-7* delims=.:/,- " %%a IN (`ECHO %DATE%_%TIME%`) DO (SET myStartTime=%%a%%b%%c%%d%%e%%f%%g)
  20. SET myColumnQuery="select top 0 * into [#columns_%myStartTime%_%aRandomNumber%] from (%theQuery%) q; select stuff((select char(9) + c.name from tempdb.sys.columns c where c.object_id = t.object_id order by c.column_id for XML path(''), type).value('.', 'varchar(max)'), 1,1,'') AS Header from tempdb.sys.tables t where t.name like '#columns_%myStartTime%_%aRandomNumber%%%'"
  21. SET myHeaderFile=%theFile%.%aRandomNumber%.header
  22. SET myDataFile=%theFile%.%aRandomNumber%.data
  23. SET myLogFile=%theFile%.%myStartTime%_%aRandomNumber%.log
  24. :checks
  25. IF "%theQuery%"=="" (
  26. GOTO syntax
  27. )
  28. IF "%theFile%"=="" (
  29. GOTO syntax
  30. )
  31. IF "%theServer%"=="" (
  32. SET theServer=%COMPUTERNAME%
  33. )
  34. :information
  35. ECHO Start Time: %myStartTime% >> "%myLogFile%" 2>&1
  36. ECHO Random Number: %aRandomNumber% >> "%myLogFile%" 2>&1
  37. ECHO File: %theFile% >> "%myLogFile%" 2>&1
  38. ECHO Server Name: %theServer% >> "%myLogFile%" 2>&1
  39. ECHO Query: >> "%myLogFile%" 2>&1
  40. ECHO. >> "%myLogFile%" 2>&1
  41. ECHO %theQuery% >> "%myLogFile%" 2>&1
  42. :export
  43. BCP %myColumnQuery% queryout "%myHeaderFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1
  44. IF ERRORLEVEL 1 GOTO error
  45. BCP "%theQuery%" queryout "%myDataFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1
  46. IF ERRORLEVEL 1 GOTO error
  47. ECHO. >> "%myLogFile%" 2>&1
  48. ECHO Merging files... >> "%myLogFile%" 2>&1
  49. ECHO. >> "%myLogFile%" 2>&1
  50. COPY /A "%myHeaderFile%" + "%myDataFile%" "%theFile%" /B /Y >> "%myLogFile%" 2>&1
  51. IF ERRORLEVEL 1 GOTO error
  52. :cleanup
  53. DEL "%myHeaderFile%" >NUL 2>&1
  54. IF ERRORLEVEL 1 GOTO error
  55. DEL "%myDataFile%" >NUL 2>&1
  56. IF ERRORLEVEL 1 GOTO error
  57. IF /I NOT [%theDebug%]==[Y] (
  58. DEL "%myLogFile%"
  59. )
  60. IF ERRORLEVEL 1 GOTO error
  61. GOTO end
  62. :error
  63. ECHO
  64. ECHO ERROR: An export error has occured!
  65. IF NOT [%myLogFile: =%]==[] (
  66. ECHO Details can be found in:
  67. ECHO %myLogFile%
  68. )
  69. ECHO
  70. EXIT /B 1
  71. :syntax
  72. ECHO.
  73. ECHO SYNTAX: %0 "sql query" "output file" [server] [Y]
  74. ECHO -------------------------------------------------------------------------------
  75. ECHO You must specify an SQL query and an output file name in which the results of
  76. ECHO the query will be stored. Specifying a server is optional and defaults to the
  77. ECHO server you are executing on. If a fourth argument is given as Y a log file of
  78. ECHO the command outputs will be saved in the same folder as the output file.
  79. ECHO -------------------------------------------------------------------------------
  80. :end
  81. REM This is the end.

小结:

1、导出带有列名的Excel,可以用BCP,语句最少,但导出的不是真正的Excel文件;

2、使用OpenRowset,可以导出真正的Excel;

3、使用NPOI,可以最大化地满足编程人员的需求,另外也可在导出时再做适当的逻辑处理,另外也不需要xp_cmdshell等额外的权限;

4、最简单的是使用SSIS的导出向导,界面直观,可以直接导出为Excel 2003/2007格式。

SQL Server带列名导出到Excel(Export to CSV with headers)的几个思路的更多相关文章

  1. sql server 表结构 导出 到excel

    SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, -- 字段序号 = a.colorder, 字段 ...

  2. 从SQL Server中导入/导出Excel的基本方法(转)

    从sql server中导入/导出 excel 的基本方法 /*=========== 导入/导出 excel 的基本方法 ===========*/ 从excel文档中,导入数据到sql数据库中,很 ...

  3. 不同版本的SQL Server之间数据导出导入的方法及性能比较

    原文:不同版本的SQL Server之间数据导出导入的方法及性能比较 工作中有段时间常常涉及到不同版本的数据库间导出导入数据的问题,索性整理一下,并简单比较下性能,有所遗漏的方法也欢迎讨论.补充. 0 ...

  4. 在SQL Server中将数据导出为XML和Json

        有时候需要一次性将SQL Server中的数据导出给其他部门的也许进行关联或分析,这种需求对于SSIS来说当然是非常简单,但很多时候仅仅需要一次性导出这些数据而建立一个SSIS包就显得小题大做 ...

  5. SQL Server服务器上需要导入Excel数据的必要条件

    SQL Server服务器上需要导入Excel数据,必须安装2007 Office system 驱动程序:数据连接组件,或者Access2010的数据库引擎可再发行程序包,这样就不必在服务器上装Ex ...

  6. SQL Server 2008 R2导出数据脚本的方法

    以前看到有些朋友说必须SQL Server 2008才能导出包含数据的脚本,后来仔细研究发现其实SQL Server 2008 R2也是可以的,只需在导出的时候在高级中设置一下即可. 1.首先在数据库 ...

  7. Sql Server 带参数的存储过程执行方法

    Sql Server 带参数的存储过程执行方法 Visual C# 动态操作 SQL Server 数据库实例教程(4):带参数的存储过程执行方法 上一篇文章介绍了带参数的SQL语句执行方法和不带参数 ...

  8. sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同

    原文:sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同 说明: 以前要将一个表中的数据导出为脚本,只有用存储过程.现在在SQL Server ...

  9. 连接到 PostgreSQL 数据源(SQL Server 导入和导出向导)

    本主题向你介绍如何从 SQL Server 导入和导出向导的“选择数据源”页或“选择目标”页连接到 PostgreSQL 数据源. 重要 连接到 PostgreSQL 数据库的详细需求和先决条件不在此 ...

随机推荐

  1. 【vue 权威指南】 学习笔记 二

    1.指令 1.1内部指令 基础指令:v-show , v-else , v-model , v-repeat , v-for , v-text , v-el , v-html , v-on , v-b ...

  2. 归并排序 ALDS1_5_B:Merge Sort

    Merge Sort Write a program of a Merge Sort algorithm implemented by the following pseudocode. You sh ...

  3. 在阿里云IIS服务器上安装证书

    在IIS服务器上安装证书 您可将下载的阿里云SSL证书安装到IIS服务器上,使您的IIS服务器支持HTTPS安全访问. 一.前提条件 申请证书时需要选择 系统自动创建CSR. 申请证书时如果选择手动创 ...

  4. Android_侧滑菜单的实现

    1.创建侧滑菜单Fragment package com.example.didida_corder; import android.os.Bundle; import android.view.La ...

  5. K3/Cloud 用插件打开一张已存在的单据

    BillShowParameter billpara = new BillShowParameter();billpara.FormId = "SAL_SaleOrder";//单 ...

  6. [APIO2010] 回文串 - 回文自动机

    经典题吧 我觉得我要换个板子,这结构体板子真TM不顺手 #include <bits/stdc++.h> using namespace std; const int N = 2e6 + ...

  7. vue formatter element表格处理数据

    formatter 指定一个vue methods 方法 作用:对从数据库中取出的数据进行处理后展示. <el-table-column prop="partner1" // ...

  8. Python目录结构规范

    在设计大型项目时需要规范目录结构. 假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了: Foo/ |-- bin/ | |-- foo | |-- foo/ | |-- tests ...

  9. linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二)

    linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二) 安装apache web容器 . yum方式安装apache 注意apache在linux ...

  10. easyui只显示年月,时间格式

    <div > <input id="db" /> </div> <script> /*power by showbo http:// ...