大数据量导出Excel ---待测试
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
/*--數(shù)據(jù)導(dǎo)出EXCEL
導(dǎo)出查詢(xún)中的數(shù)據(jù)到Excel,包含字段名,文件為真正的Excel文件
如果文件不存在,將自動(dòng)創(chuàng)建文件
如果表不存在,將自動(dòng)創(chuàng)建表
基于通用性考慮,僅支持導(dǎo)出標(biāo)準(zhǔn)數(shù)據(jù)類(lèi)型
--Modify
1、修改鄒建的錯(cuò)誤:關(guān)于provider的書(shū)寫(xiě)
在openrowset時(shí)為database
在ADODb.connection.open時(shí)為data source,一個(gè)很不容易找到的錯(cuò)誤,否則0x80004005 Microsoft JET Database Engine 不能執(zhí)行選定查詢(xún)
2、執(zhí)行過(guò)程過(guò)長(zhǎng)時(shí),中途無(wú)法取消
3、一些限制
--Jet SQL無(wú)法修改列名,應(yīng)使用ADOX.Catagory
--SQLServer2005索引最大為1284 bytes,order by 最大為8060 bytes
--grant exec分配不了權(quán)限
4、要對(duì)@varQuerySQL中結(jié)果集排序,請(qǐng)?jiān)?#64;varOrderBy指定結(jié)果集中的列,存儲(chǔ)過(guò)程會(huì)按此排序,不要再在@varQuerySQL中再排序
--鄒建 2003.10(引用請(qǐng)保留此信息)--*/
/*--調(diào)用示例--
--表的聯(lián)合
p_QueryToExcel @varQuerySQL= 'select top 65000 A.* from a inner join B on A.a1=B.a1'
,@varExcelFullPath= 'E:\aa21.xls',@varSheetName= 'sheet'
select * from liupeng --256003
--102400條記錄
--時(shí)間:
--@varQuerySQL沒(méi)有order by TopName,Identitier
1:50,1:21, 1:55, 1:27(加索引), 1:34(加索引)
--@varQuerySQL有order by
大于9:00
--Select語(yǔ)句列必須帶函數(shù)的列必須有別名
p_QueryToExcel @varQuerySQL= 'select MetaID as 標(biāo)識(shí),Title as 書(shū)名,Creator as 作者,Publisher as 出版者,Price as 單價(jià),CopyNum as 復(fù)本數(shù),Identitier as 分類(lèi)號(hào),TopName as 類(lèi)目,issuedate as 出版時(shí)間,ISBN,publishdate as 公布時(shí)間,(case
when IsRef= 0 then ''否''
when IsRef = 1 then ''是''
else '''' end ) as 是否教參
from [liupeng]
where CategoryTypeID=1 ',@varExcelFullPath= 'E:\aa3.xls',@varSheetName= 'sheet'
select count(*) from ast_document --334138
--102400條記錄
--時(shí)間:
--@varQuerySQL沒(méi)有order by TopName,Identitier
2:00, 1:10, 1:27, 1:21, 1:20
p_QueryToExcel @varQuerySQL=' select top 2000 MetaID as 標(biāo)識(shí),TopIdentitier,DocID,Title,Creator,Publisher,Price,CopyNum,Identitier,TopName,substring(convert(varchar, issuedate, 20), 1, 7) as 出版日期,ISBN,substring(convert(varchar,publishdate, 20), 1, 10) as 發(fā)布日期,(case
when IsRef= 0 then''否''
when IsRef = 1 then ''是''
else ''''end ) as IsRef
,Abstract
from [liupeng]'
,@varExcelFullPath= 'E:\aa004.xls',@varSheetName= 'sheet',@varOrderBy='TopIdentitier,DocID'
p_QueryToExcel @varQuerySQL= 'select top 102400
DocID,
MetaTypeID,
MetaID,
Title,
Creator,
[Year],
Publisher,
PublishDate,
Price,
ISBN,
IssueDate,
IsScan,
Status,
InsertedTime,substring(Abstract,1,255) as 摘要 from ast_document'
,@varExcelFullPath= 'E:\aa2.xls',@varSheetName= 'sheet',@varOrderBy='MetaID,Title'
--Excel 12:[Sheet1$]則,會(huì)報(bào)錯(cuò)“書(shū)簽無(wú)效”,應(yīng)使用'select * from [Sheet1$]'
insert into OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=D:\test.xlsx;',
'select * from [Sheet1$]') select top 10 DocID from Test.dbo.ast_document
--在Excel 12中一個(gè)sheet中加入10萬(wàn)條記錄比在多個(gè)Sheet中加入10萬(wàn)條記錄要滿(mǎn)很多
--因此不用Excel 12存
SELECT *
FROM OPENDATASOURCE( 'Microsoft.Jet.OLEDB.4.0',
'Data Source=F:\aa.xls; Extended properties="Excel 8.0;HDR=YES"')...sheet$
*/
ALTER proc [dbo].[p_QueryToExcel]
@varQuerySQL varchar(8000), --@varQuerySQL:查詢(xún)語(yǔ)句,各列必須有名稱(chēng),沒(méi)有的需要?jiǎng)e名,由于
--如果查詢(xún)語(yǔ)句中使用了order by,請(qǐng)加上top 100 percent
--對(duì)是否包含where分類(lèi)限制不做要求
@varExcelFullPath nvarchar(4000), --@varExcelFullPath:生成Excel的完整路徑
@varSheetName varchar(512) = 'sheet',
@varOrderBy varchar(512) = '類(lèi)目', --必須是@varQuerySQl中的列名
@varArrayHiddenCols varchar(1024) = 'TopIdentitier,DocID'
as
begin
--聲明和初始化變量
declare @varSheetName_pre varchar(1024)
declare @intOneSheetMaxNumber int
declare @intRecCount int
declare @sinSheetNumber smallint
declare @sinCircle int
declare @varTempSQL varchar(8000)
set @intOneSheetMaxNumber = 50000
set @sinSheetNumber = 1
set @varExcelFullPath = convert(varchar(8000),ltrim(rtrim(@varExcelFullPath)))
set @varQuerySQL = lower(ltrim(rtrim(@varQuerySQL)))
set @sinCircle = 0
set @varSheetName_pre = @varSheetName
set @varOrderBy = ltrim(rtrim(@varOrderBy))
set @varArrayHiddenCols = lower(ltrim(rtrim(@varArrayHiddenCols)))
--select top 1 1 from ast_document where metaid not in ('CategoryTypeID','DocID')
set @varArrayHiddenCols = replace(@varArrayHiddenCols,',',',') --CategoryTypeID,DocID
print @varArrayHiddenCols
-- set @varOrderByWithNoAliasTable = ltrim(rtrim(@varOrderByWithNoAliasTable))
-- --@varQuerySQL的別名這里取AAA
-- if @varOrderByWithNoAliasTable is null or @varOrderByWithNoAliasTable = ''
-- set @varOrderBy = 'Order by AAA.CategoryTypeid, AAA.HiberarchyCode'
-- else
-- set @varOrderBy = 'AAA.' + replace(@varOrderByWithNoAliasTable,',' ,',AAA.' )
/*=================================檢測(cè)參數(shù)有效性====================*/
----判斷@varExcelFullPath
if (@varExcelFullPath is null) or (@varExcelFullPath='')
begin
RAISERROR ('Excel文件路徑不能為空。',1,1)
return 50001
end
----判斷@varQuerySQL
if (@varQuerySQL is null) or (@varQuerySQL = '')
begin
RAISERROR ('查詢(xún)語(yǔ)句不能為空。',1,2)
return 50001
end
----判斷@varQuerySQL 'SQL語(yǔ)句'
----假設(shè)用戶(hù)沒(méi)有惡意調(diào)用
set @varTempSQL = @varQuerySQL
if left(@varTempSQL,1) = '('
begin
RAISERROR ('不能將整個(gè)SQL語(yǔ)句用括號(hào)包起來(lái)。',2,16)
return 50002
end
if charindex('select ',@varTempSQL,1) = 0
begin
RAISERROR ('Error 缺少select語(yǔ)句。',2,16)
return 50002
end
if charindex(' aaa',@varTempSQL,1) > 0 or charindex(' bbb',@varTempSQL,1) > 0 or charindex(' myrownumber',@varTempSQL,1) > 0
begin
RAISERROR ('請(qǐng)使用AAA、BBB、MyRowNumber以外的別名。',2,16)
return 50002
end
if left(@varTempSQL,1) = '('
begin
RAISERROR ('不能將整個(gè)SQL語(yǔ)句用括號(hào)包起來(lái)。',2,16)
return 50002
end
--針對(duì)'
--set @varQuerySQL = replace(@varQuerySQL,char(39),char(39)+char(39))
/*
if charindex(char(39),@varTempSQL,1) > 0
begin
--RAISERROR ('Error 傳輸?shù)腟QL語(yǔ)句不能包含英文撇,請(qǐng)使用''代替。',3,17)
--return 50002
end
*/
if @varOrderBy is null or @varOrderBy =''
begin
RAISERROR ('排序不能為空。',1,5)
return 50001
end
else
begin
set @varOrderBy = 'BBB.' + replace(@varOrderBy,',',',BBB.')
end
print @varOrderBy
--exec ('select 1 from (select * from ast_document where docid < 0) as A')
--select 1以便得到count記錄數(shù),保證@varQuerySQL不包含AAA別名
set @varTempSQL = 'select 1 from (' + @varQuerySQL + ') as AAA'
exec (@varTempSQL)
--@@rowcount在下一個(gè)begin...end之后就成為0
set @intRecCount = @@rowcount
if @intRecCount = 0
begin
RAISERROR ('查詢(xún)記錄集為空。',1,5)
return 50001
end
print @intRecCount
declare @varTopCategoryCode varchar(256)
declare @varTopCategoryName varchar(512)
declare @err int, @src varchar(255), @desc varchar(255), @out int --Error跟蹤
declare @obj int, @constr varchar(1000), @fdlist varchar(8000), @fdlist_AAA varchar(8000)
declare @tbname sysname
--檢查Excel文件是否已經(jīng)存在
create table #tb(a bit,b bit,c bit)
set @varExcelFullPath = ltrim(rtrim(@varExcelFullPath))
insert into #tb
exec master..xp_fileexist @varExcelFullPath
print 'xp_fileexist'+@varExcelFullPath
--select * from #tb
/*
xp_fileexist 返回的三個(gè)列, 分別代表
文件已存在 文件是目錄 父目錄已存在
----- ----- ------
0 0 1
*/
/*
declare @saveas varchar(2048),@sheet int
set @saveas = 'ActiveWorkbook.SaveAs("'+@varExcelFullPath+'")'
exec @err = sp_oacreate 'excel.application' ,@obj output
if @err <> 0 goto lberr
exec @err = sp_oamethod @obj ,'workbooks.add' ,@sheet output
if @err <> 0 goto lberr
exec @err = sp_oamethod @obj ,@saveas
if @err <> 0 goto lberr
--exec @err = sp_oamethod @obj ,'ActiveWorkbook.Save'
if @err <> 0 goto lberr
exec @err = sp_oamethod @obj ,'Workbooks.Close'
if @err <> 0 goto lberr
exec @err = sp_oamethod @obj ,'quit'
exec @err = sp_oadestroy @obj
return
*/
--數(shù)據(jù)庫(kù)創(chuàng)建語(yǔ)句
set @varTempSQL = @varExcelFullPath
if exists(select 1 from #tb where a=1)
begin
--set @constr= 'DRIVER={Microsoft Excel Driver (*.xls)};DSN= '''';READONLY=FALSE '
-- + ';CREATE_DB= "'+@sql+ '";DBQ='+@sql
RAISERROR ('暫不支持對(duì)已經(jīng)存在的Excel,做導(dǎo)出操作。',1,5)
return 50001
end
else
set @constr= 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+@varExcelFullPath+ ';Extended Properties="Excel 8.0;HDR=YES"'
--set @constr= 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source='+@varExcelFullPath+ ';Extended Properties="Excel 12.0;HDR=YES"'
--連接數(shù)據(jù)庫(kù)
EXEC @err=sp_OACreate 'ADODB.Connection', @obj OUT
print '連接數(shù)據(jù)庫(kù)1'+convert(varchar(50),@obj)
if @err <> 0 goto lberr
EXEC @err=sp_OASetProperty @obj,'ConnectionString', @constr
if @err <> 0 goto lberr
exec @err=sp_oamethod @obj, 'Open'
print '連接數(shù)據(jù)庫(kù)2'+@constr
if @err <> 0 goto lberr
print '創(chuàng)建臨時(shí)表1'
--創(chuàng)建相同表結(jié)構(gòu)的臨時(shí)表
set @tbname= '##tmp_'+convert(varchar(38),newid())
set @varTempSQL= 'select top 1 AAA.* into ['+@tbname+ '] from ('+@varQuerySQL+ ') AAA'
print '創(chuàng)建臨時(shí)表2'+@varTempSQL
exec(@varTempSQL)
set @varTempSQL = ''
set @fdlist = ''
set @fdlist_AAA = ''
select @fdlist=@fdlist+ ',['+a.name+']'
,@varTempSQL=@varTempSQL+',['+a.name+'] '
+case
when b.name like '%char'
then case when a.length> 255 then 'text(255)'
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)
and charindex(a.name, @varArrayHiddenCols)=0
select @fdlist_AAA=@fdlist_AAA+ ',AAA.['+a.name+']'
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)
and charindex(a.name, @varArrayHiddenCols)=0
print @fdlist + ' ' +@fdlist_AAA
print'轉(zhuǎn)換數(shù)據(jù)類(lèi)型'
/*=====================分頁(yè)插入Excel的Sheet=======================*/
--如果不按分類(lèi)存放
--獲得記錄總數(shù)@intRecCount,上面判斷時(shí)已經(jīng)獲得
----設(shè)置Sheet名稱(chēng)
----判斷@intRecCount與@intOneSheetMaxNumber大小,定義Sheet名稱(chēng)后
----分頁(yè)插入各個(gè)Sheet
--如果<=@intOneSheetMaxNumber
if @intRecCount <= @intOneSheetMaxNumber
begin
set @varSheetName = @varSheetName_pre + '1'
--直接創(chuàng)建Excel和導(dǎo)入數(shù)據(jù)
set @varTempSQL= 'create table ['+@varSheetName + '] ('
+ substring(@varTempSQL,2,8000)+ ')'
set @fdlist=substring(@fdlist,2,8000)
set @fdlist_AAA=substring(@fdlist_AAA,2,8000)
print '準(zhǔn)備創(chuàng)建Table '+@varTempSQL
exec @err=sp_oamethod @obj, 'Execute',@out out,@varTempSQL
if @err <> 0 goto lberr
--為導(dǎo)入數(shù)據(jù)
set @varTempSQL= 'openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=Yes;database='+@varExcelFullPath+ ''',['+@varSheetName+ '$])'
--set @varTempSQL= 'openrowset(''Microsoft.ACE.OLEDB.12.0'',''Excel 12.0;HDR=Yes;database='+@path+@fname+ ''',''select * from ['+@varSheetName+ '$]'')'
print '導(dǎo)入數(shù)據(jù):'+'insert into '+@varTempSQL+ '('+@fdlist+ ') select '+@fdlist_AAA+ ' from ('+@varQuerySQL+ ') as AAA'
exec('insert into '+@varTempSQL+ '('+@fdlist+ ') select '+@fdlist_AAA+ ' from ('+@varQuerySQL+ ') as AAA')
end
--如果>@intOneSheetMaxNumber
else
begin
set @sinSheetNumber = @intRecCount / @intOneSheetMaxNumber
+ (case (@intRecCount % @intOneSheetMaxNumber) when 0 then 0 else 1 end)
set @fdlist=substring(@fdlist,2,8000)
set @fdlist_AAA=substring(@fdlist_AAA,2,8000)
while ( @sinCircle < @sinSheetNumber )
begin
set @varSheetName = @varSheetName_pre + convert(varchar(50),@sinCircle+1)
print '第 ' + convert(varchar(50),@sinCircle+1) + ' 個(gè)Sheet / 總共 ' + convert(varchar(50),@sinSheetNumber) + ' 個(gè)Sheet'
--直接創(chuàng)建Excel和導(dǎo)入數(shù)據(jù)
declare @varTempSQL2 varchar(8000)
set @varTempSQL2 = ''
select @varTempSQL2= 'create table ['+@varSheetName
+ '] ('+substring(@varTempSQL,2,8000)+ ')'
print '準(zhǔn)備創(chuàng)建Table ' + @varTempSQL2
exec @err=sp_oamethod @obj, 'Execute',@out out,@varTempSQL2
print 'create table :'+@varTempSQL
if @err <> 0 goto lberr
--為導(dǎo)入數(shù)據(jù)
/*
WITH OrderedTable AS
(
SELECT BBB.*,ROW_NUMBER() OVER (ORDER BY Docid) AS 'MyRowNumber'
FROM (@varQuerySQL) as BBB
)
insert into openrowset() (@fdlist)
SELECT @fdlist
FROM OrderedTable
WHERE MyRowNumber BETWEEN (@intOneSheetMaxNumber * @sinCircle) AND (@intOneSheetMaxNumber * (@sinCircle+1))
*/
--set @varTempSQL= 'openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=Yes;database='+@varExcelFullPath+ ''',['+@varSheetName+ '$])'
--set @varTempSQL= 'openrowset(''Microsoft.ACE.OLEDB.12.0'',''Excel 12.0;HDR=Yes;database='+@path+@fname+ ''',''select * from ['+@varSheetName+ '$]'')'
set @varTempSQL2 = 'WITH OrderedTable AS
(
SELECT BBB.*,ROW_NUMBER() OVER (ORDER BY '+@varOrderBy +') AS ''MyRowNumber''
FROM (' + @varQuerySQL + ') as BBB
)
insert into openrowset(''MICROSOFT.JET.OLEDB.4.0'',''Excel 8.0;HDR=Yes;database='+@varExcelFullPath+ ''',['+@varSheetName+ '$])'
+ ' select ' + @fdlist + ' FROM OrderedTable WHERE MyRowNumber BETWEEN ' + convert(varchar(50),@intOneSheetMaxNumber * @sinCircle+1) + ' AND ' + convert(varchar(50),@intOneSheetMaxNumber * (@sinCircle+1))
print '導(dǎo)入數(shù)據(jù):'+@varTempSQL2
exec(@varTempSQL2)
set @sinCircle = @sinCircle + 1
end
end
--關(guān)閉和釋放OA對(duì)象
EXEC @err=sp_OAMethod @obj, 'Close'
EXEC @err=sp_OAMethod @obj, 'Dispose'
print 'sp_oadestroy'+convert(varchar(50),@obj)
EXEC @err=sp_OADestroy @obj
set @varTempSQL= 'drop table ['+@tbname+ ']'
print 'drop table '+@varTempSQL
exec(@varTempSQL)
return
lberr:
exec sp_oageterrorinfo 0,@src out,@desc out
lbexit:
select cast(@err as varbinary(4)) as 錯(cuò)誤號(hào)
,@src as 錯(cuò)誤源,@desc as 錯(cuò)誤描述
select @varTempSQL,@constr,@fdlist
end
轉(zhuǎn)載于:https://www.cnblogs.com/y0umer/archive/2011/09/29/3839295.html
總結(jié)
以上是生活随笔為你收集整理的大数据量导出Excel ---待测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 基于NHibernate的三层结构应用程
- 下一篇: 会话、进程组与僵死进程