【问题标题】:Bulk Insert a File with a Text Field with Carriage Return (Enters)批量插入带有回车符的文本字段的文件(Enters)
【发布时间】:2010-12-11 09:07:12
【问题描述】:

我在批量插入包含数据类型文本字段的文件时遇到问题,它包含输入,字段的分隔符是管道“|”并且行终止符是“|\n”

我收到文本字段旁边的字段截断错误。我认为批量插入认为第二个字段中的输入是下一行。

DECLARE @sql varchar(2000)
PRINT 'xyz table'
SET @sql = 
'BULK INSERT xyz 
   FROM ''\\' + @@servername + '\Import\xyz.txt''
   WITH 
      (
                DATAFILETYPE   = ''char'',
                FIELDTERMINATOR         = ''|'',
                ROWTERMINATOR           = ''|\n'',
                TABLOCK,
                ROWS_PER_BATCH         = 2000,
                MAXERRORS      = 1000

                )
'
PRINT @sql
EXECUTE (@sql)
PRINT ''
GO

这是数据示例

467507**|**08-20-09\
[8:55:03 AM] *** miked@wkaiser-6793 is Not Available [Ext. away]\(CR)
[9:00:57 AM] *** miked@wkaiser-6793 is Online [Online]\(CR)
[9:01:00 AM] <jeffp> Howdy.  Time slip update game!  Update TS#467493 & 467507 with a (CR)comment and see if you win! [9:01:30 AM] *** miked@wkaiser-6793 is Away [Away]\
\(CR)
08-18-09\(CR)
[10:13:15 AM] *** miked@wkaiser-6793 is Online [Online]\(CR)
[10:13:59 AM] <jeffp> Howdy; welcome back from lunch..  Just pinging you for an update in TS#467493 & 467507.  Since 467493 is pri9, want a stock e-mail to go out to the customer to get them moving?\(CR)
[10:14:47 AM] <miked@wkaiser-6793> thats ok i got it\(CR)
[10:14:53 AM] <jeffp> Aiight.**|**2009-08-18 00:00:00**|**2009-08-20 00:00:00**|**JDP**|**JDP**|**

表架构是:

create table xyz
  (
    xyz_id VARCHAR(200), --INT TO VARCHAR
    notes text,
    create_date varchar(32), --DATETIME
    create_user varchar(12),
    modify_date varchar(32), --DATETIME
    modify_user varchar(12)
  )

如您所见(好吧,看不到),有输入(标有 CR),批量插入将它们与新行混淆。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 你怎么知道一行何时真正结束?
  • 您确定行终止符是\n,而不是\r 或\r\n?
  • 最后一行是“|\n”,紧接着第二个JDP

标签: sql sql-server bulkinsert bcp termination


【解决方案1】:

数据不一致。您有一些以 \(cr) 结尾的行,其中一个字段,其他 (cr) 以 | 结尾列分隔符

要么你有不一致的列分隔符,一些\(cr),一些|。 如果是这样,那么您将需要一个 format file 来处理每个单独的“列”。

【讨论】:

    【解决方案2】:

    编辑:您不需要格式文件:

    IF OBJECT_ID('tempdb..#rawdata') IS NOT NULL DROP TABLE #rawdata
    create table #rawdata (
      xyz_id VARCHAR(200)
    , notes text
    , create_date varchar(32)
    , modify_date varchar(32)
    , create_user varchar(12)
    , modify_user varchar(12)
    )
    
    BULK INSERT #rawdata 
    FROM 'C:\temp\file.txt'
    WITH (
        FIELDTERMINATOR = '**|**'
      , ROWTERMINATOR = '**|**\n'
      , TABLOCK
      )
    
    SELECT * FROM #rawdata
    

    您可能需要使用**|**\n (LF) vs **|**\r\n (CRLF) vs **|**\r (CR),具体取决于文件是 Unix、DOS 还是 MAC-like。

    /编辑

    没有格式文件就无法完成。所以,创建一个格式文件:

    8.0
    7
    1 SQLCHAR 0 0 "**|**" 1 xyz_id        ""
    2 SQLCHAR 0 0 "**|**" 2 notes         ""
    3 SQLCHAR 0 0 "**|**" 3 create_date   ""
    4 SQLCHAR 0 0 "**|**" 4 modify_date   ""
    5 SQLCHAR 0 0 "**|**" 5 create_user   ""
    6 SQLCHAR 0 0 "**|**" 6 modify_user   ""
    7 SQLCHAR 0 0 "\n"    0 omitted       ""
    

    然后:

    IF OBJECT_ID('tempdb..#rawdata') IS NOT NULL DROP TABLE #rawdata
    create table #rawdata (
      xyz_id VARCHAR(200)
    , notes text
    , create_date varchar(32)
    , modify_date varchar(32)
    , create_user varchar(12)
    , modify_user varchar(12)
    )
    
    BULK INSERT #rawdata 
    FROM '\\folder\file.txt'
    WITH (
        FORMATFILE = '\\folder\file.fmt'
      , TABLOCK
      )
    

    或者,在 SQL 2005+ 中:

    SELECT * FROM OPENROWSET(
        BULK '\\folder\file.txt'
      , FORMATFILE = '\\folder\file.fmt'
      ) a
    

    【讨论】:

    • 谢谢彼得!!,我马上试试。您的示例比我查看的文档更完整、更准确。
    • 彼得,我尝试了解决方案,但我得到了同样的错误。我将格式文件中的“\n”修改为“|\n”。我收到此错误:服务器:消息 4866,级别 17,状态 66,第 1 行批量插入失败。数据文件中第 1 行第 1 列的列太长。请确保正确指定了字段终止符和行终止符。服务器:消息 7399,级别 16,状态 1,第 1 行 OLE DB 提供程序“STREAM”报告错误。提供商没有提供有关该错误的任何信息。 OLE DB 错误跟踪 [OLE/DB 提供程序 'STREAM' IRowset::GetNextRows 返回 0x80004005:
    • 这意味着它找不到分隔符,只是继续读取直到填满缓冲区。更改格式文件之前的错误消息是什么?我会尝试一些事情: 1. 将一百行复制到一个单独的文件中并尝试首先使其工作。此外,使用 SELECT FROM OPENROWSET(....) 单独测试格式文件。如果你能做到这一点,你就大大缩小了问题的范围。
    • 我使用您的示例文本进行测试、复制并粘贴到文本编辑器中、将行相乘等。确实使用了上面显示的所有方法。跨度>
    • 是什么系统生成的文件? CR 通常表示回车、十进制 13、0x0D 或“\r”,而不是“\n”。 “\n”表示换行,十进制10,0x0A。 Windows 系统生成 \r\n 行尾,而 Unix 系统生成 \n。如果你有一个十六进制编辑器,你可以打开文件,看看里面到底有什么。 \n 为 0A,\r 为 0D,\r\n 为 0D 0A。如果行之间不一致,则必须找到其他方法来识别新行。
    猜你喜欢
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    相关资源
    最近更新 更多