BULK INSERT / OPENROWSET用于CSV文件的FormatFile Terminator,数据中包含(逗号)

时间:2012-07-16 14:30:42

标签: sql sql-server c#-4.0 bulkinsert openrowset

我为我的百万行CSV编写了一个很好的导入,它工作得非常好(使用OPENROWSET BULK(我没有使用BULK INSERT,因为我需要与其他一些列交叉连接).formatfile使用逗号作为终结者。

以下是我用于开发的CSV示例:

Reference, Name, Street
1,Dave Smith, 1 Test Street
2,Sally SMith,1 Test Street

一旦我开始工作,有人提醒我数据本身可能有一个逗号,哎呀!!!!

Reference, Name, Street
"1","Dave Smith", "1 Test Street"
"2","Sally Smith","1,Test Street" <-comma in street

人们如何使用FormatFiles处理数据中包含逗号的CSV? (或者我只是说文件必须以TAB分隔)?

2 个答案:

答案 0 :(得分:2)

如果您的字段终止符可以出现在数据中,那么最好使用TAB或PIPE分隔符(或任何适用于您的数据的分隔符)。

  

如果数据中出现终止符,则将其解释为   终结符,而不是数据,以及该字符后面的数据   解释为属于下一个字段或记录。因此,   仔细选择你的终结者,以确保它们永远不会出现   在您的数据中

http://msdn.microsoft.com/en-us/library/ms191485.aspx

答案 1 :(得分:0)

数据字段中的分隔符是分隔文件的常见问题。解决这个问题的一些常见策略包括:

  1. 重新创建数据文件,并在将数据字段写入文件之前从数据字段中删除所有分隔符:这会消除OPENROWSET错误,但不会保留数据的完整性。
  2. 使用不同的分隔符重新创建数据文件:根据我的经验,制表符分隔符是更好的选择。在数据中遇到制表符而不是逗号是不常见的。但它肯定不是闻所未闻的。我也看过数据中的标签。
  3. 用双引号括起数据字段:这需要对XML格式文件进行一些调整。
  4. 手动编辑数据文件可能适用于上述任何选项。但它可能很乏味,特别是对于大文件。 (只需在Notepad.exe中打开几个GB的文件就可以耐心等待。)实际上,您希望作者为您重新创建它。选项#1应始终“工作”。但同样,您可能无法忍受数据完整性问题。选项#2可能适用于许多情况,但它不是防弹的。选项#3也不是防弹(它总是可能在数据字段中有一个分隔符),但它尽可能接近。此外,它还保留了数据完整性。

    以下是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="5"/>
      <FIELD ID="2" xsi:type="CharTerm" TERMINATOR='","' MAX_LENGTH="128" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
      <FIELD ID="3" xsi:type="CharTerm" TERMINATOR='"\r\n' MAX_LENGTH="128" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
     </RECORD>
     <ROW>
      <COLUMN SOURCE="1" NAME="Reference" xsi:type="SQLVARYCHAR"/>
      <COLUMN SOURCE="2" NAME="Name" xsi:type="SQLVARYCHAR"/>
      <COLUMN SOURCE="3" NAME="Street" xsi:type="SQLVARYCHAR"/>
     </ROW>
    </BCPFORMAT>
    

    注意FIELD TERMINATOR:我使用单引号将","标识为终结符,将"\r\n标识为行结束符(COLUMN 3终止符)。我做了一个有根据的猜测,NameStreet最多为128个字符 - 根据需要进行编辑。

    问题:

    1. OPENROWSET()查询将返回带有Reference双引号字符的"。因此......
    2. Reference不能作为INT(或SMALLINT,BIGINT等)返回。它将作为VARCHAR(xsi:type="SQLVARYCHAR"
    3. 返回

      对于提供的特定数据样本,我会从Reference数据字段中删除双引号,调整XML格式文件,以便FIELD ID="1"具有TERMINATOR=',"',并进一步调整XML格式文件,以便COLUMN SOURCE="1"具有xsi:type="SQLINT"

      有关其他信息,请参阅此博客文章:Getting Started With OPENROWSET and the BULK Rowset Provider - Part 2