一个Excel导入SQL server的例子(分别使用游标、CTE、master..spt_values实现)

本文介绍了如何使用 SQL Server 2008 将 Excel 数据导入到表中,并通过循环导入特定月份的数据。包括使用 OpenRowset、游标和 CTE 方法实现数据导入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQL Server 2008中SQL应用系列--目录索引

 转自邀月

有人提问如下:

这个是Excel的,比如是test.xls
欠费年份 欠费开始月份 欠费结束月份 应缴金额(月租)  
2001 9 12 94.4  
2008 5 12 88.8  
2010 8 12 90.4
___________________________________________

这个是表:比如是a表
a(pk,int,not null) //主键,自动增长
b(varchar(19),null) //费款所属期
c(decimal(10,2),null) //应缴金额___________________________________________

现在我要将test.xls中的数据导入到a表,从开始月份到结束月份要做循环导入,比如第一条2001年的从9月到12月要录入4条数据到a表,导入后的格式如:
select * from a

a b c
1 2001-09 94.4
2 2001-10 94.4
3 2001-11 94.4
4 2001-12 94.4

数据库是:MS Sql server 2008

解析:

思路一:可以使用OpenRowset查询导入到表变量中,再用游标循环赋值。方法如下:

  1. use testdb2  
  2. go  
  3. /*******************建立测试数据***3w@live.cn***********************/  
  4. IF NOT OBJECT_ID('[TBTest]') IS NULL  
  5.     DROP TABLE [TBTest]  
  6. GO  
  7. CREATE TABLE [TBTest](  
  8. [tid] int identity(1,1) primary key,  
  9. [date] NVARCHAR(20) null,  
  10. [Money] decimal(10,2) null)  
  11. go  
  12. /*******************启用Ad Hoc Distributed Queries***3w@live.cn***********************/   
  13. --------USE master  
  14. --------go  
  15. --------sp_configure 'show advanced options', 1  
  16. --------GO  
  17. ------------reconfigure   
  18. ----------启用分布式查询 Ad Hoc Distributed Queries  
  19. --------sp_configure 'Ad Hoc Distributed Queries', 1   
  20. --------GO  
  21. --------reconfigure   
  22. --------go  
  23. use testdb2  
  24. go  
  25. /*******************定义表变量***3w@live.cn***********************/   
  26. Declare @TableVar table  
  27. (PKId int primary key identity(1,1)  
  28. ,RYear int not null,BMonth int not null  
  29. ,EMonth int not null,RMoney Decimal(15,2) not null  
  30. )  
  31. insert into @TableVar  
  32. (RYear ,BMonth ,EMonth ,RMoney)  
  33. select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0',   
  34. 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:/test/test20110501.xls',   
  35. 'select * from [Sheet1$]')   
  36. ----select RYear,BMonth,EMonth,RMoney from @TableVar   
  37. ------update @TableVar   
  38. ------SET d1=cast(  
  39. ------Cast(RYear as Nvarchar(4))+'-'+cast(BMonth AS nvarchar(2))+'-01' as date)  
  40. ------, d2=cast(  
  41. ------Cast(RYear as Nvarchar(4))+'-'+cast(EMonth AS nvarchar(2))+'-01' as date)  
  42. /*******************第一种方法,用游标***3w@live.cn***********************/   
  43.     DECLARE @RYear int  
  44.     declare @BMonth int  
  45.     declare @EMonth int  
  46.     declare @RMoney int  
  47.     DECLARE DateDemo_cursor CURSOR FOR   
  48.     select RYear,BMonth,EMonth,RMoney from @TableVar where 1=1  
  49.     OPEN DateDemo_cursor  
  50.     FETCH NEXT FROM DateDemo_cursor  
  51.     INTO @RYear,@BMonth,@EMonth,@RMoney  
  52.         WHILE @@FETCH_STATUS = 0  
  53.         BEGIN  
  54.           
  55.             --修改记录  
  56.            while(@EMonth-@BMonth>=0)  
  57.                begin  
  58.                 insert INTO [TBTest]  
  59.                 SELECT TOP 1 cast(RYear  AS nvarchar(4))+'-'+  
  60.                 CASE WHEN (@BMonth<10) THEN '0'+cast(@BMonth AS nvarchar(2))  
  61.                 ELSE cast(@BMonth AS nvarchar(2)) END,  
  62.                 Rmoney from @TableVar where Ryear=@RYear   
  63.                   
  64.                 SET @BMonth=@BMonth+1   
  65.                end  
  66.             --修改结束  
  67.             FETCH NEXT FROM DateDemo_cursor into @RYear,@BMonth,@EMonth,@RMoney  
  68.               
  69.         END  
  70.     CLOSE DateDemo_cursor  
  71.     DEALLOCATE DateDemo_cursor  
  72.       
  73. GO  
  74. SELECT * FROM [TBTest]  

查询结果:

  1. /*  
  2. tid date    Money  
  3. 1   2001-09 94.40  
  4. 2   2001-10 94.40  
  5. 3   2001-11 94.40  
  6. 4   2001-12 94.40  
  7. 5   2008-05 88.80  
  8. 6   2008-06 88.80  
  9. 7   2008-07 88.80  
  10. 8   2008-08 88.80  
  11. 9   2008-09 88.80  
  12. 10  2008-10 88.80  
  13. 11  2008-11 88.80  
  14. 12  2008-12 88.80  
  15. 13  2010-08 90.40  
  16. 14  2010-09 90.40  
  17. 15  2010-10 90.40  
  18. 16  2010-11 90.40  
  19. 17  2010-12 90.40  
  20. */  

评价:该方法使用了最传统的方法,思路清晰。但没有体现SQL server 2008的语法特性,略显繁琐。

思路二:可否使用CTE实现?(KillKill提供)

  1. /*******************第二种方法,用CTE,适用于sql2005/2008/2008 r2*********/  
  2. /***************************************3w@live.cn***********************/   
  3. TRUNCATE table [TBTest]  
  4. go  
  5. Declare @TableVar table  
  6. (PKId int primary key identity(1,1)  
  7. ,RYear int not null,BMonth int not null  
  8. ,EMonth int not null,RMoney Decimal(15,2) not null  
  9. );  
  10. insert into @TableVar(RYear ,BMonth ,EMonth ,RMoney)  
  11. select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0',   
  12. 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:/test/test20110501.xls',   
  13. 'select * from [Sheet1$]');  
  14. with seq as (select top 12 row_number() over (order by object_id) val   
  15.   from sys.objects)  
  16. select   
  17.   cast(t.RYear  AS nvarchar(4))+'-'+  
  18.         CASE WHEN (t.BMonth+seq.val<10) THEN '0'+cast(t.BMonth+seq.val AS nvarchar(2))  
  19.         ELSE cast(t.BMonth+seq.val AS nvarchar(2)) END  
  20.         ,RMoney c  
  21. from @TableVar t inner join seq   
  22. on t.BMonth+seq.val <= EMonth;  

思路三:可否使用SQL Server 2008新提供的Merge实现?

思路四:使用NPOI在业务层实现数据转换。

思路五:用Master..spt_values表实现(由小F提供)

利用该表,可获取一定区间内的列表,最长不超过2048,如

  1. select number from master..spt_values  
  2. where type='P' and  
  3. number between 1 and 5  
  4. /*  
  5. number  
  6. 1  
  7. 2  
  8. 3  
  9. 4  
  10. 5  
  11. */   

因为月份最多12,不超过2048,因此可以利用 master..spt_values。

  1. /*******************第五种方法,用master..spt_values,适用于sql2005/2008/2008 r2*********/  
  2. /***************************************3w@live.cn***********************/  
  3. Declare @TableVar table  
  4. (PKId int primary key identity(1,1)  
  5. ,RYear int not null,BMonth int not null  
  6. ,EMonth int not null,RMoney Decimal(15,2) not null  
  7. ----,d1 date null,d2 Date null  
  8. );  
  9. insert into @TableVar  
  10. (RYear ,BMonth ,EMonth ,RMoney)  
  11. select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0',  
  12. 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:/test/test20110501.xls',  
  13. 'select * from [Sheet1$]');  
  14. select  
  15. tid=row_number()over(order by getdate()),ltrim(RYear)+'-'+ltrim(right(100+number,2)) as date,  
  16.      b.RMoney as money  
  17. from  
  18. master..spt_values a, @TableVar b  
  19. where  
  20. number between BMonth and EMonth  
  21. and  
  22. type='p'  

思路六:使用SSIS实现

 

SSIS导入IIS 日志的简单示例
注意:sql 2008 的话,配置期间,需要配置SQL外围配置管理器:
右键点击sql服务器,选择方面,然后选择外围应用配置器,将AdHocRemoteQueriesEnabled  配置为True

执行出错:消息 7308,级别 16,状态 1,第 1 行
因为 OLE DB 访问接口 'Microsoft.Jet.OLEDB.4.0' 配置为在单线程单元模式下运行,所以该访问接口无法用于分布式查询。

折腾了一天终于解决了,原因是:在64SQL Engine中已经不提供jet.oledb.4.0的驱动了
解决方法:下载一个ACE.Oledb.12.0 for X64位的驱动,并把连接字符串Microsoft.jet.Oledb.4.0 更改为 Microsoft.ACE.OLEDB.12.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值