如何确保 BULK INSERT 将按顺序插入我的平面文件行?

Posted

技术标签:

【中文标题】如何确保 BULK INSERT 将按顺序插入我的平面文件行?【英文标题】:How can I ensure that a BULK INSERT will insert my flat file's rows in order? 【发布时间】:2016-06-09 13:04:02 【问题描述】:

我有一个由多行文本组成的平面文件,没有字段分隔符(我按位置解析它们)并且用换行符作为行分隔符。基本上是这样的:

FIELD1AFIELD2AFIELD3AFIELD4A...
FIELD1BFIELD2BFIELD3BFIELD4B...
FIELD1CFIELD2CFIELD3CFIELD4C...

在将其解析到最终表之前,我使用以下命令将其批量插入到临时表中:

BULK INSERT TEMPTABLE
FROM 'c:\location\file' 
WITH (FIELDTERMINATOR= '',ROWTERMINATOR = '\n',MAXERRORS = 0)

现在,第一行和最后一行用作文件的标题和结尾,并包含特殊信息。因此,它们不遵循“FIELD1AFIELD2AFIELD3AFIELD4A ...”的相同模式,因此我需要考虑它们。此外,我需要专门在另一个表中插入标题行的信息。

但是当我运行批量插入时,行并没有按顺序插入到临时表中,所以我不能只假设顶部寄存器将是标题,而最后一个寄存器将是尾部。

有没有办法强制批量插入不遵循平面文件中的行顺序?我没有“键列”,也没有索引,也没有文件中的任何内容,并且无法在此文件中插入行号(我需要保留收到的内容,并且太大而无法复制或修改无论如何)。

谢谢

【问题讨论】:

"但是当我运行批量插入时,行没有按顺序插入"你怎么知道的?我问是因为SELECT 不一定会按照插入的顺序返回它们。 在你的临时表上创建一个标识列怎么样?批量插入将按文件顺序插入,您的问题是您的选择可能不会按顺序排列,因此您添加一个标识列并选择按它排序。 @RBarryYoung:嗯,这就是问题所在。当我从临时表过渡到最终表时,我会通过 INSERT INTO...SELECT 来完成。此外,在需要标题的第一行时,我做了一个 SELECT TOP 1 * FROM TEMPTABLE,所以我知道该查询没有返回标题行 @JorgeCampos:如果我在临时表中添加标识列,我会收到此错误:Msg 4866, Level 16, State 1, Line 1 批量加载失败。数据文件中第 1 行第 54 列的列太长。验证是否正确指定了字段终止符和行终止符。消息 7399,级别 16,状态 1,第 1 行链接服务器“(null)”的 OLE DB 提供程序“BULK”报告了错误。提供商没有提供有关该错误的任何信息。消息 7330,级别 16,状态 2,第 1 行无法从链接服务器“(null)”的 OLE DB 提供程序“BULK”获取行。 很可能是因为它试图将第一个值插入 ID 列。您必须使用格式文件,请参阅此线程:***.com/questions/14711814/… 【参考方案1】:

我记得(有一段时间没做过了)以下是适合我的步骤:

    不要使用临时表,而是使用永久表(名称 Temp_<something>,如果需要),您只需在使用 BULK INSERT 之前删除/截断即可。

    更改 Temp_<something> 以添加 ID 列并将其设为此表的聚集主键。

    创建视图:

.

CREATE VIEW Temp_something_View As
    SELECT
          (every column EXCEPT the ID column)
    FROM Temp_something

GO

.

    现在批量插入视图而不是表。

现在 ID 值最低和最高的行应该是输入源的第一行和最后一行。

当您需要源输入顺序中的行时,只需使用ORDER BY ID 从表中选择。否则它将根据某些物理分配约束而不是按照您想要的逻辑顺序返回它们。

【讨论】:

如果我在临时表中添加该列(作为永久表)然后创建视图,当我执行批量插入时,我会收到以下消息:“消息 2601,级别 14,状态 1,第 1 行无法插入重复键行,重复键为 " 好的,如果我将 ID 列定义为具有标识的主键,它确实有效。我会把你的答案标记为正确的,谢谢。现在,我还想问:使用这种方法而不是您推荐的使用聚集索引的方法是否会降低性能?再次感谢 这是避免格式化文件的绝妙方法(尤其是sinve BULK INSERT 不能使用格式化文件)。但是,ANYONE 是否可以确认添加 IDENTITY 将正确地按顺序标记行。我找不到任何权威来证实这一点。 @Nick.McDermaid 我从未见过 Microsoft 确认这可以保证按顺序分配 ID。但是,它一直对我有用(现在已经超过 15 年了),我能想到的唯一可能导致它失败的事情就是它是否进行了并行插入,所以我想说,只要确保它是不要那样做。只要表上有索引,就应该防止任何并行插入。另外,虽然我从未尝试过,但文档确实说 BULK INSERT 可以使用 FormatFile。 @VenerableAgents 请注意,Aaron 正在测试的具体不是我在上面概述的。我在 identity 列上有一个聚集索引。我已经在这个配置上做了很多次像 Aaron 一样的测试,只要你不尝试向 BULK INSERT 添加任何并行性,它就可以工作。正如我在回答中指出的那样,微软不保证这一点,但很难看出为什么它不起作用。像 Aaron 那样使用备用聚集索引显然会给导入器一个重新排序行的理由。【参考方案2】:

确保从源数据集中以正确的顺序选择数据。

【讨论】:

以上是关于如何确保 BULK INSERT 将按顺序插入我的平面文件行?的主要内容,如果未能解决你的问题,请参考以下文章

获取 Bulk.Insert() -Mongoskin 的插入 ID

bulk.insert(doc) 默认值无法插入 MongoDB nodejs

bulk.insert(doc) 默认值无法插入 MongoDB nodejs

SQL Bulk Insert 快速插入

高效的MySQL的批插入 BULK INSERT

SSIS常用的包—大量插入任务(Bulk Insert task)