Office中国论坛/Access中国论坛

标题: 批量导入(bulk insert)csv文件到SQL server [打印本页]

作者: roych    时间: 2020-7-4 16:27
标题: 批量导入(bulk insert)csv文件到SQL server
前不久在某个论坛(ExcelHome)上有人问,能否批量导入数据到SQL server?虽然之前也有数据同步的情况,但需要导入文件的情况极少,所以也就手动按向导完成罢了。
这么一问,倒是把我问到了。终于今天得闲,就抽空去微软官网看看。导入大概有三种方式。一种是bcp,一种是bulk insert,另一种则是openrowset。

bcp只能对最简单的格式进行导入,不能指定表头(或许我没找到这方面的例子吧)。而openrowset则通常需要格式化文件(fmt)或者指定数据库链接引擎(例如,access)等参数,对于文本文件,bulk insert似乎更简单一些。所以这里只谈谈bulk insert。
按惯例,先上代码。
  1. CREATE PROC [dbo].[import_data] @start_date date='2020-07-01', @end_date date='2020-07-31'
  2. AS
  3. BEGIN
  4.         DECLARE @file_name varchar(100)--文件名
  5.         DECLARE @day_num int--天数
  6.         DECLARE @date date--日期变量
  7.         DECLARE @i int--序号变量
  8.         DECLARE @tmp_table table(is_file_exists int,is_path int,is_parent_exists int)--文件信息变量表,字段1:是否存在文件。字段2:是否文件夹,字段3:父级路径是否存在
  9.         DECLARE @str_sql varchar(500)--SQL语句拼接
  10.         --初始化起止日期天数,用于确定循环上限
  11.         SET @day_num=DATEDIFF(day,@start_date,@end_date)
  12.         --初始化日期变量。
  13.         SET @date=@start_date
  14.         SET @i=0

  15.         WHILE @i<=@day_num

  16.         BEGIN
  17.                 SET @file_name='E:\AppData\Local\'+convert(varchar(8),@date,112)+'.csv'
  18.                 INSERT INTO @tmp_table EXEC [MASTER]..XP_FILEEXIST @file_name --把文件信息插入文件信息变量表

  19.                 IF EXISTS(SELECT * FROM @tmp_table WHERE is_file_exists=1) --如果文件存在,则拼接SQL语句
  20.                         SET @str_sql= 'BULK INSERT v_test FROM '''+@file_name
  21.                                                         +''' WITH (FIRSTROW=2,FIELDTERMINATOR='','')'
  22.                 ELSE --否则就跳出循环
  23.                         BREAK
  24.                
  25.                 delete from test where import_date=@date --如果已经导入,则删除数据
  26.                 EXEC(@str_sql) --导入数据
  27.                 update test set import_date=@date where import_date is null --添加导入日期
  28.                 DELETE FROM @tmp_table --删除文件信息变量表。注意,这里可不能truncate。
  29.                 SET @i=@i+1 --循环累计
  30.                 SET @date=DATEADD(day,@i,@start_date)  --重设日期变量
  31.         END

  32. END
复制代码


先说下基本格式:
BULK INSERT 表名(或视图名)'C:\测试.csv' WITH (FIRSTROW=2,FIELDTERMINATOR=',')
说明:
FIRSTROW=2:可选(默认情况下从第一行导入)。这里表示从第二行导入。
FIELDTERMINATOR=',':必选,表示csv分割符为逗号。SQL server 2017版本【即版本号为14以上】以后可以用FORMAT='CSV'代替这一句。

版本号查看请参考下图:
[attach]63815[/attach]
附件如下:
[attach]63816[/attach]




作者: roych    时间: 2020-7-4 16:27
其实存储过程里的注释已经写得很清楚了。不过我还是想讲下思路,便于大家理解。
在讲解之前,我们先做这么一个假设。
假定这批CSV文件都是以日期命名的,当然,你也可以加上前缀,例如,“被割韭菜20200701.csv”,不过,不建议具体到时分秒,更不建议加后缀名,这样处理难度比较大。
接下来我们大体画个流程图(看不清流程图的话,请自行下载附件[attach]63824[/attach]):
[attach]63822[/attach]大体需要做3个判断。

解决方案:

综上,我们需要定义的变量有:

添加完毕后,就是写存储过程了。大家可以看上面的帖子,注释应该算比较详尽的,就不一一解析了。
如果还有什么问题,也可以在后面的帖子上评论或回复。


作者: admin    时间: 2020-7-4 17:56
赞一个
作者: Excel3000    时间: 2021-1-6 10:15
牛,感谢分享,大数据导入很实用,节省不少时间
作者: worryd1    时间: 2023-11-6 20:36
这个应该非常有用,先收藏一下




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3