zoukankan      html  css  js  c++  java
  • Sql server bulk insert

    Bulk Insert


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

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

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

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

    bulk insert test
    from 'f:	est.txt'
    with
    (fieldterminator=',',
    rowterminator='
    ',
    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: est.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="
    " 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:	est.txt'
    WITH
    (
        FORMATFILE = 'G:format.xml',
        FIELDTERMINATOR=',',
        ROWTERMINATOR='
    ',
        FIRSTROW = 2
    )

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

    疑难解答


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

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

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

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

    实验发现当我用十六进制ASCII码声明bulk insert的ROWTERMINATOR参数后,sql server成功识别出了文件中每一行结束的位置。同样如果换行符是' ',那么我们可以声明ROWTERMINATOR为十六进制ASCII码0x0d。所以当你使用常规字符(例如' '、' '等)来给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

  • 相关阅读:
    WPF换肤之八:创建3D浏览效果
    ADPlus
    由INotifyPropertyChanged,BindingList绑定引发的跨线程异常及其解决办法
    无服务器端的UDP群聊功能剖析(重构版本)
    A Short Guide to DBI[转]
    绑定到异步的ObservableCollection
    使用反射+缓存+委托,实现一个不同对象之间同名同类型属性值的快速拷贝
    ORM查询语言(OQL)简介概念篇
    无需重新编译代码,在线修改表单
    LJMM平台( Linux +Jexus+MySQL+mono) 上使用MySQL的简单总结
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/8355586.html
Copyright © 2011-2022 走看看