數(shù)據(jù)庫:bcp生成excel文件優(yōu)化方案

字號(hào):

一、綜述:
    目前頁面生成excel的方法很多,總結(jié)起來,不外乎兩類,一種是使用excel對(duì)象,一種是“偽文件”。兩種方法是各自有各自的優(yōu)缺點(diǎn),在不同的領(lǐng)域也都有很多成功的案例。前者使用對(duì)象的方式很靈活,可以生成任意表現(xiàn)方式的excel文件,缺點(diǎn)也很明顯,比如在asp下,使用excel如果發(fā)生異常,excel對(duì)象的資源是不會(huì)釋放的,也就是說在特殊情況下會(huì)把服務(wù)器“拖死”。后者的方式一般使用的是html文件,但是后綴是xls,也就是“偽文件”,這樣的操作在生成excel文件的時(shí)候,對(duì)比第一種方法系統(tǒng)開銷比較小,但是由于是“偽文件”,在打開文件的時(shí)候會(huì)有提示,但是由于生成html的方法很多,也是目前在我們系統(tǒng)中采用比較多的方式,另外他生成復(fù)雜樣式的時(shí)候也比較方便,可以采用tr td的方式加上style.
    二、方案說明
    下面我要說的這種方式,是目前能找到的最快的生成excel文件的方式,姑且叫做“bcp生成csv”方法吧。它有以下幾個(gè)適用的范圍。
    1.生成的excel格式比較單一,沒有合并列等情況
    2.生成的文件格式為csv,但是可以用excel默認(rèn)打開
    3.執(zhí)行的存儲(chǔ)過程用戶需要xp_cmdshell權(quán)限
    接下來,說說它的好處:
    1.生成效率很高,由于是并發(fā)操作,每1000條數(shù)據(jù)傳送一次
    2.生成的文件沒有冗余代碼,全部為數(shù)據(jù)信息,保證了文件是所有類型中最小的
    3.沒有office2003中的excel的單sheet的6萬多行的限制,就算輸出10萬條數(shù)據(jù)也能正常生成,但是用excel2003打開失敗,用excel2007打開正常,但是由于使用上的不方便,就寫了一個(gè)存儲(chǔ)過程,只需要傳遞幾個(gè)參數(shù)進(jìn)去,就能自動(dòng)生成對(duì)應(yīng)的excel文件。先貼上代碼:
    三、代碼
    1USE [student]
    2GO
    3/**//****** 對(duì)象: StoredProcedure [dbo].[proc_2csv]腳本日期: 12/30/2008 12:01:17 ******/
    4SET ANSI_NULLS ON
    5GO
    6SET QUOTED_IDENTIFIER ON
    7GO
    8/**//**************************************************************
    9/************* copyright by James.wang(天生我豺)***************
    10/************* 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明原作者**********************
    11/************* email:ec0312@163.com **************************/
    12
    13create PROCEDURE [dbo].[proc_2csv]
    14(
    15--參數(shù)聲明
    16@sql1 varchar(4000)=’’,--from之前的SQL語句
    17@sql2 varchar(4000)=’’,--from之后的SQL語句
    18@columneName varchar(4000)=’’--顯示的列名,用英文,分割
    19
    20)
    21
    22AS
    23BEGIN
    24Set NOCOUNT ON
    25Declare @ErrNum int,
    26@tablename varchar(200),
    27@ErrInfo varchar(400),
    28
    29@outfilename varchar(200),
    30@tmpsql varchar(8000),
    31@cursql varchar(8000),
    32@csv varchar(8000)
    33set @tablename=’student.dbo.[tmp_’+Convert(varchar(50),newID())+’]’
    34
    35
    36 set @tmpsql=@sql1+’ into ’+ @tablename + ’ ’+@sql2
    37  38 exec (@tmpsql)
    39 --print @tmpsql
    40 if @@ERROR<>0
    41 begin
    42select @ErrNum=50001,@ErrInfo=’生成物理表錯(cuò)誤’
    43goto On_Error
    44 end
    45
    46set @tmpsql=’’
    47set @cursql=’’
    48set @outfilename=right(@tablename,len(@tablename)-12)
    49
    50/**//*column替換*/
    51set @columneName=replace(@columneName,’,’,’’’’’,’’’’’)
    52set @columneName=’’’’’’+@columneName+’’’’’’
    53
    54/**//*組合輸出字符*/
    55Declare @curColName varchar(20)
    56Declare currentcur cursor for
    57select t2.name from sysobjects t1,syscolumns t2 where t1.id=t2.id and t1.xtype=’U’ and
    58
    59t1.id=object_id(@outfilename)
    60Open currentcur
    61FETCH NEXT From currentcur into @curColName
    62
    63WHILE @@FETCH_STATUS = 0
    64BEGIN
    65set @cursql=@cursql+’’’’’’’’’+’+@curColName+’,’
    66FETCH NEXT From currentcur into @curColName
    67END
    68CLOSE currentcur
    69DEALLOCATE currentcur
    70set @cursql=left(@cursql,len(@cursql)-1)
    71set @tmpsql=’select ’+@columneName+’ union all select ’+@cursql+’ from ’+@tablename
    72--print @tmpsql
    73
    74/**//*導(dǎo)出數(shù)據(jù)到csv*/
    75set @csv=’master..xp_cmdshell ’’bcp "’+ @tmpsql +’" queryout  76
    77d:edufewebdufenew’+@outfilename+’.csv -c  -t","  -r"n" -S"172.16.4.*"  -U"sa"  -
    78
    79P"password" ’’ ’
    80  81--print @csv
    82exec(@csv)
    83
    84/**//*刪除臨時(shí)表*/
    85if exists(select 1 from [dbo].[sysobjects] where id = object_id(@tablename) and type = ’U’)
    86begin
    87 set @tmpsql=’drop table ’+@tablename
    88 exec(@tmpsql)
    89 if @@ERROR<>0
    90  begin
    91select @ErrNum=50002,@ErrInfo=’刪除物理表錯(cuò)誤’
    92goto On_Error
    93 end
    94  end
    95
    96Set NOCOUNT OFF
    97select @outfilename
    98Set NOCOUNT ON
    99return
    100
    101On_Error:
    102  if exists(select 1 from [dbo].[sysobjects] where id = object_id(@tablename) and type = ’U’)
    103  begin
    104 set @tmpsql=’drop table ’+@tablename
    105 exec(@tmpsql)
    106  end
    107raiserror @ErrNum @ErrInfo
    108Return
    109END
    四、代碼說明
    1.@sql1:傳入sql語句中的from的前面的語句
    2.@sql2:傳入sql語句中的from的后面的語句,考試大提示包括from
    3.@columneName:傳入顯示的列標(biāo)題,用英文的逗號(hào)分割
    4.例子:
    /*測(cè)試
    [proc_2csv] ’select top 1000 userid,cardname,cardid,studentname,case sex when ’’1’’ then ’’男’’
    else ’’女’’ end sex’,’from registersys’,’用戶名,證件類型,證件號(hào)碼,姓名,性別’
    */
    五、補(bǔ)充說明:
    1.如果傳入的sql語句中有單引號(hào),在傳入之前替換成兩個(gè)單引號(hào)
    2.如果傳入的sql語句有英文的逗號(hào),替換成全角的逗號(hào)
    3.注意master..xp_cmdshell代碼中的172.16.4.*替換成你機(jī)器ip,后面替換成對(duì)應(yīng)的帳戶和密碼,注意這個(gè)
    帳戶必須有xp_cmdshell的權(quán)限
    六、引申:
    很多人會(huì)說用sa不安全,用xp_cmdshell不安全,確實(shí)是這樣,但是我們可以采用臨時(shí)授予當(dāng)前用戶執(zhí)行系統(tǒng)
    擴(kuò)展存儲(chǔ)過程權(quán)限,這個(gè)方面我也正在學(xué)習(xí),如果大家有這方面的想法可以一起探討。
    以下是找到的一些資源:
    1.如何在不提升用戶權(quán)限的情況下,使普通用戶執(zhí)行xp_cmdshell存儲(chǔ)過程
    http://blog.csdn.net/puddingpudding/archive/2008/12/04/3445833.aspx
    2.重新設(shè)置代理和 SQLAgentCmdExec 帳戶
    http://support.microsoft.com/kb/264155/zh-cn