【问题标题】:Determine ROW that caused "unexpected end of file" error in BULK INSERT?确定在 BULK INSERT 中导致“文件意外结束”错误的 ROW?
【发布时间】:2012-05-08 21:57:05
【问题描述】:

我正在批量插入:

DECLARE @row_terminator CHAR;
SET @row_terminator = CHAR(10); -- or char(10)

DECLARE @stmt NVARCHAR(2000);
SET @stmt = '
  BULK INSERT accn_errors
   FROM ''F:\FullUnzipped\accn_errors_201205080105.txt''
   WITH 
      (
        firstrow=2,
FIELDTERMINATOR = ''|''  ,
ROWS_PER_BATCH=10000
   ,ROWTERMINATOR='''+@row_terminator+'''
   )'
exec sp_executesql @stmt;

并收到以下错误:

Msg 4832, Level 16, State 1, Line 2
Bulk load: An unexpected end of file was encountered in the data file.
Msg 7399, Level 16, State 1, Line 2
The OLE DB provider "BULK" for linked server "(null)" reported an error. The provider did not give any information about the error.
Msg 7330, Level 16, State 2, Line 2
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)".

有没有办法知道这个错误发生在哪一行?

我能够毫无问题地导入 10,000,000 行,然后出现错误

【问题讨论】:

  • 我建议先尝试不同的行终止符更容易。 char(10) 这样的情况并不常见。试试'\n''\r\n' - 调查生成文件的程序和操作系统也可能有用。
  • @AaronBertrand 所以无法识别该行?
  • 我不知道,不。如果您已经排除了第 2/3 行(通过设置 @Gordon 建议的 LastRow),您可以使用二进制除法快速缩小范围 - 获取文件中的行数并设置 LastRow = <half that number> - 如果错误仍然发生,将其分成两半,然后重试。很可能它是第一行数据,也可能是因为您没有将ROWTERMINATOR 与文件中的实际行终止符匹配。你试过\n\r\n 了吗?

标签: sql sql-server sql-server-2008 bulkinsert


【解决方案1】:

要找到麻烦的行,请使用错误文件说明符。

BULK INSERT myData
FROM 'C:\...\...\myData.csv'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
ERRORFILE = 'C:\...\...\myRubbishData.log' 
);

myRubbishData.log 将包含违规行和伴随文件 myRubbishData.log.txt 将为您提供文件中的行号和偏移量。

配套文件示例:

Row 3 File Offset 152 ErrorFile Offset 0 - HRESULT 0x80004005
Row 5 File Offset 268 ErrorFile Offset 60 - HRESULT 0x80004005
Row 7 File Offset 384 ErrorFile Offset 120 - HRESULT 0x80004005
Row 10 File Offset 600 ErrorFile Offset 180 - HRESULT 0x80004005
Row 12 File Offset 827 ErrorFile Offset 301 - HRESULT 0x80004005
Row 13 File Offset 942 ErrorFile Offset 416 - HRESULT 0x80004005

【讨论】:

【解决方案2】:

有趣,有趣,有趣。我还没有找到调试这些问题的好方法,所以我使用蛮力。也就是说,FirstRow 和 LastRow 选项非常有用。

从 LastRow = 2 开始并继续尝试。将结果加载到一次性表格中,您可以轻松截断该表格。

而且,您还应该记住,第一行也可能会给您带来问题。

【讨论】:

    【解决方案3】:

    我有一个使用批量导入的 csv 文件

    BULK INSERT [Dashboard].[dbo].[3G_Volume]
    FROM 'C:\3G_Volume.csv'
    WITH
    (
    FIRSTROW = 2,
    FIELDTERMINATOR = '","',
    ROWTERMINATOR = '\n'
    )
    GO
    

    通常我使用这个脚本,它没有问题,但在极少数情况下。

    我遇到了这个错误..

    “链接服务器“(null)”的 OLE DB 提供程序“BULK”报告了一个错误。提供程序没有提供有关该错误的任何信息。”

    通常,当最后一行有空白值(null)时会发生这种情况。

    您需要在 MS access db 中链接您的 csv 文件以检查数据。 (如果您的 csv 不超过 140 万行,您可以在 excel 中打开它)

    由于我的数据大约有 300 万行,我需要使用 access db。

    然后检查最后一行的空格数,然后将空行数减去 csv 的总行数。

    如果最后有 2 个空白行,总行数为 30000005 脚本会变成这样..

    BULK
    INSERT [Dashboard].[dbo].[3G_Volume]
     FROM 'C:\3G_Volume.csv'
    WITH
    (
    FIRSTROW = 2,
    FIELDTERMINATOR = '","',
    ROWTERMINATOR = '\n',
    Lastrow = 30000003
    )
    GO
    

    干杯... 男神

    【讨论】:

      【解决方案4】:

      如果 CHAR(10) 是行终止符,我认为您不能像在 BULK INSERT 中那样将其放在引号中。不过,有一种未记录的方式来表示它:

      ROWTERMINATOR = '0x0A'
      

      【讨论】:

      • 谢谢,Артём。我没有意识到你也可以这样处理 char(10) !它确实有效,我应该在发表评论之前对其进行测试。
      • 即使你不知道char 10,你仍然可以成为一个好人
      • 这个小技巧拯救了我的项目。它适用于 linux 命令行上的 tsql(freetds 的一部分),而所有其他解决方案都没有。嘘。
      【解决方案5】:

      是的 - BULK INSERT 会在其错误消息中提供更多细节,而解决此问题的唯一方法是使用蛮力方法,正如 Gordon 正确指出的那样。但是,首先,根据您收到的错误,它要么不理解您的行终止符,要么文件末尾缺少行终止符。使用 FIRSTROW 和 LASTROW 将有助于确定这一点。

      因此,您需要执行以下操作:

      1. 检查文件末尾是否有行终止符。如果没有,请放入一个并重试。还要确保最后一行包含所有必要的字段。它说'EOF',那是你的问题。
      2. 您确定每行末尾都有一个 LF 吗?试试 CR (\n, 0x0D) 看看是否可行。
      3. 仍然无法正常工作?尝试设置 LASTROW=2 并重试。然后尝试 LASTROW=3。如果文件中的行数超过三行且此步骤失败,则行终止符不起作用。

      【讨论】:

        【解决方案6】:

        我遇到了同样的问题。我编写了一个 shell 脚本来在 Linux 中创建一个 .csv。我将此 .csv 带到 Windows 并尝试批量加载数据。它没有“喜欢”逗号....不要问我为什么,但是我在批量导入中更改为 * 作为分隔符,并在我的 .csv 中用 * 查找和替换逗号 .. 有效..我改成~作为分隔符,这有效...制表符也有效-它不喜欢逗号....希望这对某人有所帮助。

        【讨论】:

          【解决方案7】:

          根据我的经验,这几乎总是由最后两行中的某些内容引起的。 tail 导入文件,它仍然应该给你失败。然后在全文编辑器中打开它,您可以看到非打印字符,如 CR、LF 和 EOF。即使您不知道为什么,这应该使您能够将其整合到工作中。例如,BULK INSERT fails with row terminator on last row

          【讨论】:

            【解决方案8】:

            我通过将所有字段转换为字符串然后使用通用 FIELDTERMINATOR 解决了这个问题。这有效:

            BULK INSERT [dbo].[workingBulkInsert]  
            FROM 'C:\Data\myfile.txt' WITH (
               ROWTERMINATOR = '\n', 
               FIELDTERMINATOR = ',' 
            )
            

            我的数据文件现在看起来像这样:

            "01502","1470"
            "01504","686"
            "02167","882"
            "106354","882"
            "106355","784"
            "106872","784"
            

            第二个字段是没有双引号分隔符的十进制类型(如 1470.00)。将两者都格式化为字符串消除了错误。

            【讨论】:

              【解决方案9】:

              我有一个使用批量导入的 CSV 文件

              您需要创建一个表,并且所有列都应该可以为空,并删除最后一行中的空格,只添加那些在 excel 中可用的列。并且请不要创建主列,此过程不会自动增加身份,这就是创建错误的原因。

              我已经完成了这样的批量插入:

              CREATE TABLE [dbo].[Department](
                  [Deptid] [bigint] IDENTITY(1,1) NOT NULL,
                  [deptname] [nvarchar](max) NULL,
                  [test] [nvarchar](max) NULL,
               CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED 
              (
                  [Deptid] ASC
              )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
                  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
              ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
              GO
              
              CREATE TABLE [dbo].[Table_Column](
                  [column1] [nvarchar](max) NULL,
                  [column2] [nvarchar](max) NULL
              ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
              GO
              
              BULK INSERT Table_Column
              FROM 'C:\Temp Data\bulkinsert1.csv'
              WITH (
                  FIELDTERMINATOR = ',',
                  ROWTERMINATOR='\n' ,
                  batchsize=300000 
              );
              
              insert into [dbo].[Department] 
              select column1,column2 from Table_Column
              

              【讨论】:

              • 感谢您对 SO 的贡献。问题是关于找到失败的行,而您的答案没有回答。还有已经接受的答案。删除您的答案可能是有意义的。
              【解决方案10】:

              如果我将所有字段转换为字符串,然后使用通用字段分隔符,我就解决了这个问题。

              【讨论】:

                【解决方案11】:

                产生此错误的行没有CHAR(10) 终止符或有不必要的空格

                【讨论】:

                  猜你喜欢
                  • 2012-02-10
                  • 1970-01-01
                  • 2018-06-14
                  • 2021-05-22
                  • 1970-01-01
                  • 2011-12-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多