https://www.cnblogs.com/downmoon/archive/2012/05/04/2482995.html
SQL in SQL Server 2008 BI application series and study notes series - Table of Contents Index
A few days ago encountered a problem in the project, we need to export table from SQL Server to Excel, but the need to bring the column name. Night tried several methods, and make a summary.
It assumes that the table is as follows:
USE testDb2 GO IF NOT OBJECT_ID('Demo_A') IS NULL DROP TABLE [Demo_A] /****** Object: Table [dbo].[Demo_A] downmoon:[email protected] ******/ CREATE TABLE [dbo].[Demo_A]( [ID] int not null, [Name] [Nvarchar](20) NOT NULL ) GO INSERT [dbo].[Demo_A] SELECT 1,'郭靖' union ALL SELECT 2,'胡一刀' union ALL SELECT 3,'令狐冲' GO
If a general idea, we can use the BCP, the command is as follows:
-- To allow advanced options to be changed. EXEC sp_configure 'show advanced options', 1 GO -- To update the currently configured value for advanced options. RECONFIGURE GO -- To enable the feature. EXEC sp_configure 'xp_cmdshell', 1 GO -- To update the currently configured value for this feature. RECONFIGURE GO EXEC master..xp_cmdshell 'bcp Testdb2.dbo.Demo_A out c:\Temp.xls -c -q -S"ap4\Net2012" -U"sa" -P"sA"'
Xls file thus obtained, Sheet is no column names. But we can improve the look, give the following command (Reference: http://social.msdn.microsoft.com/forums/en-US/sqlgetstarted/thread/812b8eec-5b77-42a2-bd23-965558ece5b9/ ):
Method One: Using BCP
For convenience, I have created a stored procedure:
/****** SQL Export to xls ***************/ /* Example */ /*CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExxelWithHeader.xls'*/ /* 2012.5.4 BY tony,邀月, [email protected] */ ---- CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls' Create Procedure CPP_Export_To_Excel_With_Header ( @db_name varchar(255), @table_name varchar(255), @file_path varchar(255) ) as ----Generate column names as a recordset declare @columns varchar(8000), @sql varchar(8000) declare @HeadersOnlyFile varchar(255),@TableDataWithoutHeaders varchar(255) set @HeadersOnlyFile=replace(cast(newid() as VARCHAR(40)),'-','')+'1.xls' set @TableDataWithoutHeaders=replace(cast(newid() as VARCHAR(40)),'-','')+'2.xls' select @columns=coalesce(@columns+',','')+column_name+' as '+column_name from information_schema.columns where table_name=@table_name select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''') print @columns ----Generate column names file set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@HeadersOnlyFile+'" -c''' print @sql exec(@sql) ----Create a dummy file to have actual data set @sql='exec master..xp_cmdshell ''bcp "'+@db_name+'.dbo.'+@table_name+'" out "'+@TableDataWithoutHeaders+'" -c -t -T''' print @sql exec(@sql) --Merge File into One Final Format set @sql='exec master..xp_cmdshell ''copy /b '+@HeadersOnlyFile+'+'+@TableDataWithoutHeaders+' '+@file_path+'''' print @sql exec(@sql) --Delete temp File set @sql='exec master..xp_cmdshell ''del '+@HeadersOnlyFile+'''' exec(@sql) set @sql='exec master..xp_cmdshell ''del '+@TableDataWithoutHeaders+'''' exec(@sql)
Call the method:
CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls'
Another similar approach :( see here: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49926 ), the main idea is as follows:
Method Two:
create procedure proc_generate_excel_with_columns ( @db_name varchar(100), @table_name varchar(100), @file_name varchar(100) ) as --Generate column names as a recordset declare @columns varchar(8000), @sql varchar(8000), @data_file varchar(100) select @columns=coalesce(@columns+',','')+column_name+' as '+column_name from information_schema.columns where table_name=@table_name select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''') --Create a dummy file to have actual data select @data_file=substring(@file_name,1,len(@file_name)-charindex('\',reverse(@file_name)))+'\data_file.xls' --Generate column names in the passed EXCEL file set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@file_name+'" -c''' exec(@sql) --Generate data in the dummy file set @sql='exec master..xp_cmdshell ''bcp "select * from '+@db_name+'..'+@table_name+'" queryout "'+@data_file+'" -c''' exec(@sql) --Copy dummy file to passed EXCEL file set @sql= 'exec master..xp_cmdshell ''type '+@data_file+' >> "'+@file_name+'"''' exec(@sql) --Delete dummy file set @sql= 'exec master..xp_cmdshell ''del '+@data_file+'''' exec(@sql)
Call:
EXEC proc_generate_excel_with_columns 'your dbname', 'your table name','your file path'
If your environment is SQL Server 2005, you can have:
Method three, use sp_makewebtask, only applies to SQL Server 2005
0) the structure of table T1 A int B int X char . 1) Procedures Assistant open the Web Exec the sp_configure 'Show advanced Options',. 1 the RECONFIGURE Exec the sp_configure' the Web Assistant Procedures',. 1 the RECONFIGURE 2) performs the following statement EXEC the sp_makewebtask @outputfile = 'D: \ testing.xls', @query = '* from the Select shenliang1985..T1 the TOP 10', @colheaders =. 1, @ FixedFont = 0, the LastUpdated = 0 @, @ = resultstitle 'Querying Details' . 3) generated view EXCEl the Details Querying Last Updated: 2010-03-03 01:02:59. 263 a b x 0 0 0 2 5 1 4 10 2 6 15 3 8 20 4 10 25 5 12 30 6 14 35 7 16 40 8 18 45 9
Unfortunately, after 2008 sp_makewebtask SQL Server stored procedure canceled, subsequent versions will no longer be enabled.
Method One and Method Two is actually generated files are not real Excel file, although suffix xls, to this end, to find Zou write a stored procedure.
Method IV, using OpenRowSet:
/ * - Data export EXCEL export data to Excel query, contains the field name, the file is actually an Excel file if the file does not exist, the file will be created automatically if the table does not exist, it will automatically create a table based on a common considerations, support only export standard data types - Zou 2003.10 (quoted, please retain this information) - * / / * - call sample p_exporttb @ sqlstr = 'select * from area data' , @ path = 'c: \', @ fname = 'aa.xls', @ sheetname = 'geographical information' - * / the Create proc p_exporttb @sqlstr VARCHAR (8000), - query, if the query is used in order by, please add 100 Percent Top @path nvarchar (1000), - file storage directory @fname nvarchar (250), - the file name @sheetname varchar (250) = '' - the name of the worksheet you want to create, the default file name for the aS DECLARE the @err int, @ src nvarchar (255), @ desc nvarchar (255), @ int OUT DECLARE @obj int, @ constr nvarchar (1000), @ SQL VARCHAR (8000), @ fdlist VARCHAR (8000) - the parameter detection if isnull(@fname,'')=''set @fname='temp2012.xls' if isnull(@sheetname,'')='' set @sheetname=replace(@fname,'.','#') --检查文件是否已经存在 if right(@path,1)<>'\' set @path=@path+'\' create table #tb(a bit,b bit,c bit) set @sql=@path+@fname insert into #tb exec master..xp_fileexist @sql --数据库创建语句 set @sql=@path+@fname if exists(select 1 from #tb where a=1) set @constr='DRIVER={Microsoft Excel Driver (*.xls)};DSN='''';READONLY=FALSE' +';CREATE_DB="'+@sql+'";DBQ='+@sql else set @constr='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties="Excel 8.0;HDR=YES' if @err <> 0 goto lberr - connection database + '; DATABASE =' @ SQL + + ' "' exec @ err = sp_oacreate 'adodb.connection' exec @err=sp_oamethod @obj,'open',null,@constr if @err<>0 goto lberr --创建表的SQL declare @tbname sysname set @tbname='##tmp_'+convert(varchar(38),newid()) set @sql='select * into ['+@tbname+'] from('+@sqlstr+') a' exec(@sql) select @sql='',@fdlist='' select @fdlist=@fdlist+',['+a.name+']' ,@sql=@sql+',['+a.name+'] ' +case when b.name like '%char' then case when a.length>255 then 'memo' else 'text('+cast(a.length as varchar)+')' end when b.name like '%int' or b.name='bit' then 'int' when b.name like '%datetime' then 'datetime' when b.name like '%money' then 'money' when b.name like '%text' then 'memo' else b.name end FROM tempdb..syscolumns a left join tempdb..systypes b on a.xtype=b.xusertype where b.name not in('image','uniqueidentifier','sql_variant','varbinary','binary','timestamp') and a.id=(select id from tempdb..sysobjects where name=@tbname) if @@rowcount=0 return select @sql='create table ['+@sheetname +']('+substring(@sql,2,8000)+')' ,@fdlist=substring(@fdlist,2,8000) exec @err=sp_oamethod @obj,'execute',@out out,@sql if @err<>0 goto lberr exec @err=sp_oadestroy @obj --导入数据 set @sql='openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=YES ;DATABASE='+@path+@fname+''',['+@sheetname+'$])' exec('insert into '+@sql+'('+@fdlist+') select '+@fdlist+' from ['+@tbname+']') @ SQL = SET 'drop Table [' @ + + tbName ']' Exec (@sql) return lberr: Exec sp_OAGetErrorInfo 0, @ the src OUT, OUT @ desc lbexit: SELECT Cast (AS the @err a varbinary (. 4)) AS error number , @ src as the source of errors, @ desc as the error described the SELECT @ SQL, constr @, @ fdlist Go
To execute the stored procedure, you have to turn on the switch:
-- To allow advanced options to be changed. EXEC sp_configure 'show advanced options', 1 GO -- To allow advanced options to be changed. EXEC sp_configure 'Ole Automation Procedures', 1 GO EXEC sp_configure 'Ad Hoc Distributed Queries', 1 GO -- To update the currently configured value for advanced options. RECONFIGURE GO
Call:
@ sqlstr = p_exporttb 'the SELECT * from [Demo_A]' , @ path = 'c: \', @ fname = 'Export2xls_ByProc.xls', @ sheetname = 'employee name'
The result is indeed authentic xls file.
If you are and write programs DBA, then NPOI is your ideal choice because it is a pure native does not rely on open source third-party components Office components, it provides a " CreateExportDataTableSheetAndHeaderRow " method allows you to easily generate pure Excel, unfortunately, currently supports only seems to Excel 2003. Example Consider here ( http://scottonwriting.net/sowblog/archive/2011/06/08/export-an-ado-net-datatable-to-excel-using-npoi.aspx ), the component source: HTTP : //npoi.codeplex.com/
Method five:
protected Sheet CreateExportDataTableSheetAndHeaderRow(DataTable exportData, string sheetName, CellStyle headerRowStyle) { var sheet = this.Workbook.CreateSheet(EscapeSheetName(sheetName)); // Create the header row var row = sheet.CreateRow(0); for (var colIndex = 0; colIndex < exportData.Columns.Count; colIndex++) { var cell = row.CreateCell(colIndex); cell.SetCellValue(exportData.Columns[colIndex].ColumnName); if (headerRowStyle != null) cell.CellStyle = headerRowStyle; } return sheet; }
Of course, if you feel more than a little high threshold method, then the SSIS may be your first choice, it has the advantage of simple and intuitive, and can be exported to Excel2007 format.
Just select the first row contains the column names, you can. When you export
Method six, using SSIS
Because some people feel that the interface is too cumbersome, then follow the wizard to export the idea to write a batch, you can modify to suit their own content:
@ECHO OFF REM ------------------------------------------------------------------------------- REM Generic script for exporting data to file from SQL Server using a SQL query. REM The resulting file will be tab separated with newline as the row delimiter. REM A log file is generated and kept in case of an error or when in debug mode. REM See command syntax for details. REM REM History: REM 20120327 Lars Rönnbäck CREATED REM ------------------------------------------------------------------------------- :constants SET myCodePage=ACP :variables SET theQuery=%~1 SET theFile=%~2 SET theServer=%~3 SET theDebug=%~4 SET /a aRandomNumber=%random%%%1000 FOR /F "usebackq tokens=1-7* delims=.:/,- " %%a IN (`ECHO %DATE%_%TIME%`) DO (SET myStartTime=%%a%%b%%c%%d%%e%%f%%g) 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%%%'" SET myHeaderFile=%theFile%.%aRandomNumber%.header SET myDataFile=%theFile%.%aRandomNumber%.data SET myLogFile=%theFile%.%myStartTime%_%aRandomNumber%.log :checks IF "%theQuery%"=="" ( GOTO syntax ) IF "%theFile%"=="" ( GOTO syntax ) IF "%theServer%"=="" ( SET theServer=%COMPUTERNAME% ) :information ECHO Start Time: %myStartTime% >> "%myLogFile%" 2>&1 ECHO Random Number: %aRandomNumber% >> "%myLogFile%" 2>&1 ECHO File: %theFile% >> "%myLogFile%" 2>&1 ECHO Server Name: %theServer% >> "%myLogFile%" 2>&1 ECHO Query: >> "%myLogFile%" 2>&1 ECHO. >> "%myLogFile%" 2>&1 ECHO %theQuery% >> "%myLogFile%" 2>&1 :export BCP %myColumnQuery% queryout "%myHeaderFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error BCP "%theQuery%" queryout "%myDataFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error ECHO. >> "%myLogFile%" 2>&1 ECHO Merging files... >> "%myLogFile%" 2>&1 ECHO. >> "%myLogFile%" 2>&1 COPY /A "%myHeaderFile%" + "%myDataFile%" "%theFile%" /B /Y >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error :cleanup DEL "%myHeaderFile%" >NUL 2>&1 IF ERRORLEVEL 1 GOTO error DEL "%myDataFile%" >NUL 2>&1 IF ERRORLEVEL 1 GOTO error IF /I NOT [%theDebug%]==[Y] ( DEL "%myLogFile%" ) IF ERRORLEVEL 1 GOTO error GOTO end :error ECHO ECHO ERROR: An export error has occured! IF NOT [%myLogFile: =%]==[] ( ECHO Details can be found in: ECHO %myLogFile% ) ECHO EXIT /B 1 :syntax ECHO. ECHO SYNTAX: %0 "sql query" "output file" [server] [Y] ECHO ------------------------------------------------------------------------------- ECHO You must specify an SQL query and an output file name in which the results of ECHO the query will be stored. Specifying a server is optional and defaults to the ECHO server you are executing on. If a fourth argument is given as Y a log file of ECHO the command outputs will be saved in the same folder as the output file. ECHO ------------------------------------------------------------------------------- :end REM This is the end.
小结:
1、导出带有列名的Excel,可以用BCP,语句最少,但导出的不是真正的Excel文件;
2、使用OpenRowset,可以导出真正的Excel;
3、使用NPOI,可以最大化地满足编程人员的需求,另外也可在导出时再做适当的逻辑处理,另外也不需要xp_cmdshell等额外的权限;
4、最简单的是使用SSIS的导出向导,界面直观,可以直接导出为Excel 2003/2007格式。
SQL Server 2008中SQL应用系列及BI学习笔记系列--目录索引
前几天在项目中遇到一个问题,需要从SQL Server导出表到Excel,但需要带列名。晚上尝试了几种方法,并作个小结。
假定表如下:
USE testDb2 GO IF NOT OBJECT_ID('Demo_A') IS NULL DROP TABLE [Demo_A] /****** Object: Table [dbo].[Demo_A] downmoon:[email protected] ******/ CREATE TABLE [dbo].[Demo_A]( [ID] int not null, [Name] [Nvarchar](20) NOT NULL ) GO INSERT [dbo].[Demo_A] SELECT 1,'郭靖' union ALL SELECT 2,'胡一刀' union ALL SELECT 3,'令狐冲' GO
如果通常的思路,我们可以用BCP,命令如下:
-- To allow advanced options to be changed. EXEC sp_configure 'show advanced options', 1 GO -- To update the currently configured value for advanced options. RECONFIGURE GO -- To enable the feature. EXEC sp_configure 'xp_cmdshell', 1 GO -- To update the currently configured value for this feature. RECONFIGURE GO 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
为了方便,我创建了一个存储过程:
/****** SQL Export to xls ***************/ /* Example */ /*CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExxelWithHeader.xls'*/ /* 2012.5.4 BY tony,邀月, [email protected] */ ---- CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls' Create Procedure CPP_Export_To_Excel_With_Header ( @db_name varchar(255), @table_name varchar(255), @file_path varchar(255) ) as ----Generate column names as a recordset declare @columns varchar(8000), @sql varchar(8000) declare @HeadersOnlyFile varchar(255),@TableDataWithoutHeaders varchar(255) set @HeadersOnlyFile=replace(cast(newid() as VARCHAR(40)),'-','')+'1.xls' set @TableDataWithoutHeaders=replace(cast(newid() as VARCHAR(40)),'-','')+'2.xls' select @columns=coalesce(@columns+',','')+column_name+' as '+column_name from information_schema.columns where table_name=@table_name select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''') print @columns ----Generate column names file set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@HeadersOnlyFile+'" -c''' print @sql exec(@sql) ----Create a dummy file to have actual data set @sql='exec master..xp_cmdshell ''bcp "'+@db_name+'.dbo.'+@table_name+'" out "'+@TableDataWithoutHeaders+'" -c -t -T''' print @sql exec(@sql) --Merge File into One Final Format set @sql='exec master..xp_cmdshell ''copy /b '+@HeadersOnlyFile+'+'+@TableDataWithoutHeaders+' '+@file_path+'''' print @sql exec(@sql) --Delete temp File set @sql='exec master..xp_cmdshell ''del '+@HeadersOnlyFile+'''' exec(@sql) set @sql='exec master..xp_cmdshell ''del '+@TableDataWithoutHeaders+'''' exec(@sql)
调用方法:
CPP_Export_To_Excel_With_Header 'Testdb2','Demo_A','C:\TestExcelWithHeader.xls'
另外有类似的处理方法:(看这里:http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49926),其主要思路如下:
方法二:
create procedure proc_generate_excel_with_columns ( @db_name varchar(100), @table_name varchar(100), @file_name varchar(100) ) as --Generate column names as a recordset declare @columns varchar(8000), @sql varchar(8000), @data_file varchar(100) select @columns=coalesce(@columns+',','')+column_name+' as '+column_name from information_schema.columns where table_name=@table_name select @columns=''''''+replace(replace(@columns,' as ',''''' as '),',',',''''') --Create a dummy file to have actual data select @data_file=substring(@file_name,1,len(@file_name)-charindex('\',reverse(@file_name)))+'\data_file.xls' --Generate column names in the passed EXCEL file set @sql='exec master..xp_cmdshell ''bcp " select * from (select '+@columns+') as t" queryout "'+@file_name+'" -c''' exec(@sql) --Generate data in the dummy file set @sql='exec master..xp_cmdshell ''bcp "select * from '+@db_name+'..'+@table_name+'" queryout "'+@data_file+'" -c''' exec(@sql) --Copy dummy file to passed EXCEL file set @sql= 'exec master..xp_cmdshell ''type '+@data_file+' >> "'+@file_name+'"''' exec(@sql) --Delete dummy file set @sql= 'exec master..xp_cmdshell ''del '+@data_file+'''' exec(@sql)
调用示例:
EXEC proc_generate_excel_with_columns 'your dbname', 'your table name','your file path'
如果,你的环境是SQL Server 2005,那么可以有:
方法三,使用sp_makewebtask,仅适用于SQL Server 2005
0)表T1结构 a int b int x char 1)开启Web Assistant Procedures exec sp_configure 'show advanced options', 1 RECONFIGURE exec sp_configure 'Web Assistant Procedures', 1 RECONFIGURE 2)执行如下语句 EXEC sp_makewebtask @outputfile = 'd:\testing.xls', @query = 'Select TOP 10 * from shenliang1985..T1', @colheaders =1, @FixedFont=0,@lastupdated=0,@resultstitle='Querying details' 3)查看生成的EXCEl的 Querying details Last updated: 2010-03-03 01:02:59.263 a b x 0 0 0 2 5 1 4 10 2 6 15 3 8 20 4 10 25 5 12 30 6 14 35 7 16 40 8 18 45 9
可惜SQL Server 2008以后sp_makewebtask 这个存储过程取消了,后续版本也不再启用。
方法一和方法二其实生成的文件都不上真正的Excel文件,虽然后缀名为xls,为此,找到邹建写的一个存储过程。
方法四,使用OpenRowSet:
/*--数据导出EXCEL 导出查询中的数据到Excel,包含字段名,文件为真正的Excel文件 如果文件不存在,将自动创建文件 如果表不存在,将自动创建表 基于通用性考虑,仅支持导出标准数据类型 --邹建 2003.10(引用请保留此信息)--*/ /*--调用示例 p_exporttb @sqlstr='select * from 地区资料' ,@path='c:\',@fname='aa.xls',@sheetname='地区资料' --*/ create proc p_exporttb @sqlstr varchar(8000),--查询语句,如果查询语句中使用了order by ,请加上top 100 percent @path nvarchar(1000),--文件存放目录 @fname nvarchar(250),--文件名 @sheetname varchar(250)=''--要创建的工作表名,默认为文件名 as declare @err int,@src nvarchar(255),@desc nvarchar(255),@out int declare @obj int,@constr nvarchar(1000),@sql varchar(8000),@fdlist varchar(8000) --参数检测 if isnull(@fname,'')=''set @fname='temp2012.xls' if isnull(@sheetname,'')='' set @sheetname=replace(@fname,'.','#') --检查文件是否已经存在 if right(@path,1)<>'\' set @path=@path+'\' create table #tb(a bit,b bit,c bit) set @sql=@path+@fname insert into #tb exec master..xp_fileexist @sql --数据库创建语句 set @sql=@path+@fname if exists(select 1 from #tb where a=1) set @constr='DRIVER={Microsoft Excel Driver (*.xls)};DSN='''';READONLY=FALSE' +';CREATE_DB="'+@sql+'";DBQ='+@sql else set @constr='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties="Excel 8.0;HDR=YES' +';DATABASE='+@sql+'"' --连接数据库 exec @err=sp_oacreate 'adodb.connection',@obj out if @err<>0 goto lberr exec @err=sp_oamethod @obj,'open',null,@constr if @err<>0 goto lberr --创建表的SQL declare @tbname sysname set @tbname='##tmp_'+convert(varchar(38),newid()) set @sql='select * into ['+@tbname+'] from('+@sqlstr+') a' exec(@sql) select @sql='',@fdlist='' select @fdlist=@fdlist+',['+a.name+']' ,@sql=@sql+',['+a.name+'] ' +case when b.name like '%char' then case when a.length>255 then 'memo' else 'text('+cast(a.length as varchar)+')' end when b.name like '%int' or b.name='bit' then 'int' when b.name like '%datetime' then 'datetime' when b.name like '%money' then 'money' when b.name like '%text' then 'memo' else b.name end FROM tempdb..syscolumns a left join tempdb..systypes b on a.xtype=b.xusertype where b.name not in('image','uniqueidentifier','sql_variant','varbinary','binary','timestamp') and a.id=(select id from tempdb..sysobjects where name=@tbname) if @@rowcount=0 return select @sql='create table ['+@sheetname +']('+substring(@sql,2,8000)+')' ,@fdlist=substring(@fdlist,2,8000) exec @err=sp_oamethod @obj,'execute',@out out,@sql if @err<>0 goto lberr exec @err=sp_oadestroy @obj --导入数据 set @sql='openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=YES ;DATABASE='+@path+@fname+''',['+@sheetname+'$])' exec('insert into '+@sql+'('+@fdlist+') select '+@fdlist+' from ['+@tbname+']') set @sql='drop table ['+@tbname+']' exec(@sql) return lberr: exec sp_oageterrorinfo 0,@src out,@desc out lbexit: select cast(@err as varbinary(4)) as 错误号 ,@src as 错误源,@desc as 错误描述 select @sql,@constr,@fdlist go
为了执行这个存储过程,你得先打开以下开关:
-- To allow advanced options to be changed. EXEC sp_configure 'show advanced options', 1 GO -- To allow advanced options to be changed. EXEC sp_configure 'Ole Automation Procedures', 1 GO EXEC sp_configure 'Ad Hoc Distributed Queries', 1 GO -- To update the currently configured value for advanced options. RECONFIGURE GO
调用示例:
p_exporttb @sqlstr='select * from [Demo_A]' ,@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/
方法五:
protected Sheet CreateExportDataTableSheetAndHeaderRow(DataTable exportData, string sheetName, CellStyle headerRowStyle) { var sheet = this.Workbook.CreateSheet(EscapeSheetName(sheetName)); // Create the header row var row = sheet.CreateRow(0); for (var colIndex = 0; colIndex < exportData.Columns.Count; colIndex++) { var cell = row.CreateCell(colIndex); cell.SetCellValue(exportData.Columns[colIndex].ColumnName); if (headerRowStyle != null) cell.CellStyle = headerRowStyle; } return sheet; }
当然,如果你觉得以上方法门槛有点高,那么SSIS可能是你的首选,它的优势在于简单直观,并且可以导出为Excel2007格式。
只要在导出时选择第一行包含列名,即可。
方法六,使用SSIS
因为有人觉得界面过于繁琐,于是仿照导出向导的思路写了一个批处理,你可以修改为自己适合的内容:
@ECHO OFF REM ------------------------------------------------------------------------------- REM Generic script for exporting data to file from SQL Server using a SQL query. REM The resulting file will be tab separated with newline as the row delimiter. REM A log file is generated and kept in case of an error or when in debug mode. REM See command syntax for details. REM REM History: REM 20120327 Lars Rönnbäck CREATED REM ------------------------------------------------------------------------------- :constants SET myCodePage=ACP :variables SET theQuery=%~1 SET theFile=%~2 SET theServer=%~3 SET theDebug=%~4 SET /a aRandomNumber=%random%%%1000 FOR /F "usebackq tokens=1-7* delims=.:/,- " %%a IN (`ECHO %DATE%_%TIME%`) DO (SET myStartTime=%%a%%b%%c%%d%%e%%f%%g) 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%%%'" SET myHeaderFile=%theFile%.%aRandomNumber%.header SET myDataFile=%theFile%.%aRandomNumber%.data SET myLogFile=%theFile%.%myStartTime%_%aRandomNumber%.log :checks IF "%theQuery%"=="" ( GOTO syntax ) IF "%theFile%"=="" ( GOTO syntax ) IF "%theServer%"=="" ( SET theServer=%COMPUTERNAME% ) :information ECHO Start Time: %myStartTime% >> "%myLogFile%" 2>&1 ECHO Random Number: %aRandomNumber% >> "%myLogFile%" 2>&1 ECHO File: %theFile% >> "%myLogFile%" 2>&1 ECHO Server Name: %theServer% >> "%myLogFile%" 2>&1 ECHO Query: >> "%myLogFile%" 2>&1 ECHO. >> "%myLogFile%" 2>&1 ECHO %theQuery% >> "%myLogFile%" 2>&1 :export BCP %myColumnQuery% queryout "%myHeaderFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error BCP "%theQuery%" queryout "%myDataFile%" -T -S "%theServer%" -a 65535 -c -C %myCodePage% -q >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error ECHO. >> "%myLogFile%" 2>&1 ECHO Merging files... >> "%myLogFile%" 2>&1 ECHO. >> "%myLogFile%" 2>&1 COPY /A "%myHeaderFile%" + "%myDataFile%" "%theFile%" /B /Y >> "%myLogFile%" 2>&1 IF ERRORLEVEL 1 GOTO error :cleanup DEL "%myHeaderFile%" >NUL 2>&1 IF ERRORLEVEL 1 GOTO error DEL "%myDataFile%" >NUL 2>&1 IF ERRORLEVEL 1 GOTO error IF /I NOT [%theDebug%]==[Y] ( DEL "%myLogFile%" ) IF ERRORLEVEL 1 GOTO error GOTO end :error ECHO ECHO ERROR: An export error has occured! IF NOT [%myLogFile: =%]==[] ( ECHO Details can be found in: ECHO %myLogFile% ) ECHO EXIT /B 1 :syntax ECHO. ECHO SYNTAX: %0 "sql query" "output file" [server] [Y] ECHO ------------------------------------------------------------------------------- ECHO You must specify an SQL query and an output file name in which the results of ECHO the query will be stored. Specifying a server is optional and defaults to the ECHO server you are executing on. If a fourth argument is given as Y a log file of ECHO the command outputs will be saved in the same folder as the output file. ECHO ------------------------------------------------------------------------------- :end REM This is the end.
summary:
1, export Excel with column names, you can use BCP, the minimum sentence, but not the real export Excel files;
2, OpenRowset, you can export a real Excel;
3, using NPOI, can maximize the programmer needs, may do additional processing suitable logic when exporting, additionally does not require additional rights xp_cmdshell the like;
4, the easiest is to use the Export Wizard SSIS, intuitive interface, can be exported directly to Excel 2003/2007 format.