• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PowerCoder
博客园    首页    新随笔    联系   管理    订阅  订阅

Sql server bulk insert

Bulk Insert


Sql server 的bulk insert语句可以高效的导入大数据量的平面文件(txt,csv文件)到数据库的一张表中,其用法如下:

bulk insert test
from 'f:\test.txt'
with
(fieldterminator=',',
rowterminator='\n')

其中"test"是数据库表的名字,"f:\test.txt"是导入平面文件的地址,fieldterminator指定平面文件中列的分隔符是什么,rowterminator指定平面文件中行的结束符是什么。

 

还可以使用FIRSTROW和LASTROW限制行数。如下COPY前三行:

bulk insert test
from 'f:\test.txt'
with
(fieldterminator=',',
rowterminator='\n',
FIRSTROW =1,
LASTROW=3)

 

要把平面文件数据导入到数据库表中,平面文件只有3个字段,数据库表有7个字段,
怎么把平面文件字段的对应到表的字段,如何用bulk insert来实现?

数据库表 userinfo

CREATE TABLE userinfo
(
    id INT identity,
    userName varchar(20),
    pass varchar(20),
    address varchar(100),
    phone varchar(20),
    email varchar(128),
    registerTime datetime
)

平面文件数据是F:\test.txt

userName,address,phone 
hua,湖南,5971898
jan,重庆,2334512
wang, 北京, 100201

先在G盘存放一个格式化xml文件
G:\format.xml

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="1" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="20" COLLATION="Chinese_PRC_CI_AS"/>
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="100" COLLATION="Chinese_PRC_CI_AS"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="20" COLLATION="Chinese_PRC_CI_AS"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="userName" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="2" NAME="address" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="phone" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>

然后使用bulk insert语句时,采用FORMATFILE参数指定该format.xml文件

BULK INSERT userinfo
    FROM 'F:\test.txt'
WITH
(
    FORMATFILE = 'G:\format.xml',
    FIELDTERMINATOR=',',
    ROWTERMINATOR='\n',
    FIRSTROW = 2
)

这样bulk insert语句就会按照format.xml文件中的列映射,将平面文件F:\test.txt的三列数据,依次插入到表userinfo的userName、address、phone这三个字段上了。

 

疑难解答


 1.最好使用十六进制ASCII码来声明ROWTERMINATOR

有时候当我们的txt或csv文件的文件头没有声明文件的编码方式(比如txt或csv文件是936-GBK或者UTF-8等编码方式,但是在其文件头没有声明)时,会导致bulk insert语句的ROWTERMINATOR参数失效,比如当我在导入一个test.txt文件是936-GBK编码方式的时候,我发现明明文件中的换行符是'\n',但是当我声明ROWTERMINATOR='\n'的时候根本不起作用,bulk insert老是找不到文件中的换行符进而报错。

 

然后我通过网上查资料发现,原来bulk insert的ROWTERMINATOR参数,可以使用十六进制ASCII码来表示换行符是什么。比如'\n'的ASCII码是十进制12,十六进制0A,那么我们可以在bulk insert语句中声明0x0a来作为ROWTERMINATOR表示换行符'\n',如下所示:

BULK INSERT userinfo
    FROM 'F:\test.txt'
WITH
(
    FIELDTERMINATOR='|',
    ROWTERMINATOR='0x0a',
    FIRSTROW =1,
    LASTROW=1000,
    CODEPAGE='936'
)

实验发现当我用十六进制ASCII码声明bulk insert的ROWTERMINATOR参数后,sql server成功识别出了文件中每一行结束的位置。同样如果换行符是'\r',那么我们可以声明ROWTERMINATOR为十六进制ASCII码0x0d。所以当你使用常规字符(例如'\n'、'\r'等)来给bulk insert的ROWTERMINATOR参数赋值不起作用的时候,你可以尝试使用字符的十六进制ASCII码来给ROWTERMINATOR参数赋值,bulk insert的ROWTERMINATOR参数可以根据十六进制ASCII码准确识别出数据文件中的换行符。

 

2.使用CODEPAGE参数声明文件的编码方式

CODEPAGE参数可以声明txt或csv文件的编码方式是什么,有时候bulk insert无法识别出导入文件的编码方式,会导致从文件导入的数据是乱码,这时候如果我们知道文件的编码方式,就可以使用CODEPAGE参数告诉bulk insert文件使用的是什么编码,从而避免数据导入到数据库后变为乱码。比如上面的sql中我们就用CODEPAGE参数声明了导入文件的编码是936(GBK)

 

另外这里有一篇文章很详细的总结了使用bulk insert可能会出现的一些换行问题,大家可以参考下:

SQL Server Bulk Insert Row Terminator Issues

posted @ 2018-01-26 01:41  PowerCoder  阅读(14718)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3