【问题标题】:SQL SERVER bulk insert ignore deformed linesSQL SERVER 批量插入忽略变形的行
【发布时间】:2012-07-02 10:54:50
【问题描述】:

我必须导入 SAP 未转换列表。这些报告看起来很丑陋,不太适合自动化处理。然而,没有其他选择。数据以减号和竖线符号为边界,类似于以下示例:

02.07.2012
--------------------
Report name
--------------------
|Header1 |Header2  |
|Value 11|Value1 2 |
|Value 21|Value2 2 | 
--------------------

我使用格式文件和如下语句:

SELECT Header1, Header2
FROM  OPENROWSET(BULK  'report.txt',
FORMATFILE='formatfile_report.xml'  ,
errorfile='rejects.txt',
firstrOW = 2,
maxerrors = 100 ) as report

很遗憾,我收到以下错误代码:

Msg 4832, Level 16, State 1, Line 1
Bulk load: An unexpected end of file was encountered in the data file.
Msg 7399, Level 16, State 1, Line 1
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 1
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)".

rejects txt 文件包含文件的最后一行,其中只有减号。 rejects.txt.Error.Txt 文件:

Row 21550 File Offset 3383848 ErrorFile Offset 0 - HRESULT 0x80004005

引发错误的罪魁祸首显然是最后一行不符合格式文件中声明的格式。然而,丑陋的标题不会造成太大的问题(至少是最顶部的那个)。

虽然我定义了 maxerror 属性,但只有一条变形的线会杀死整个操作。如果我手动删除包含所有减号 (-) 的最后一行,一切正常。由于该导入将经常运行且特别无人看管,因此额外的后处理不是严肃的解决方案。

谁能帮我让 sql server 分别变得不那么挑剔和敏感。它记录了无法加载的行很好,但为什么它会中止整个操作?并且在执行导致创建 reject.txt 的语句之后,在手动删除 txt 文件之前不能执行其他(或相同)语句:

Msg 4861, Level 16, State 1, Line 1
Cannot bulk load because the file "rejects.txt" could not be opened. Operating system error code 80(The file exists.).
Msg 4861, Level 16, State 1, Line 1
Cannot bulk load because the file "rejects.txt.Error.Txt" could not be opened. Operating system error code 80(The file exists.).

我认为这是一种奇怪的行为。请帮我压制它。

编辑 - 跟进: 这是我使用的格式文件:

<?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="EMPTY" xsi:type="CharTerm" TERMINATOR="|" MAX_LENGTH="100"/>
   <FIELD ID="HEADER1" xsi:type="CharTerm" TERMINATOR="|" MAX_LENGTH="100"/>
   <FIELD ID="HEADER2" xsi:type="CharTerm" TERMINATOR="|\r\n" MAX_LENGTH="100"/>
 </RECORD>
 <ROW>
   <COLUMN SOURCE="HEADER1" NAME="HEADER2" xsi:type="SQLNVARCHAR"/>
   <COLUMN SOURCE="HEADER2" NAME="HEADER2" xsi:type="SQLNVARCHAR"/>
 </ROW>
 </BCPFORMAT>

【问题讨论】:

  • 当我使用具有固定列宽的格式文件(CharFixed 而不是 CharTerm)时,我发现了更好的支持。然后,您可以在 where 子句中检查一些列的预期内容。但是,由于 SAP 会改变列宽,这在我的用例中不是一个选项。
  • 很遗憾,SQL Server 似乎无法处理不 100% 符合所提供格式的行。为什么它不能忽略并记录该行然后继续而不是立即中止整个导入。更糟糕的是,创建了一种错误文件,并且只要存在该错误文件(未被用户或外部程序删除),就无法开始进一步的导入!这不是专业软件的奇怪行为吗?

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


【解决方案1】:

BULK INSERT 在处理不符合所提供规范的数据时是出了名的笨拙和无益。

我没有对格式文件做很多工作,但您可能需要考虑使用BULK INSERT 将文件的每一行放入带有单个nvarchar(max) 的临时登台表中列。

这使您可以将数据放入 SQL 中以供进一步检查,然后您可以使用各种字符串操作函数将其分解为最终要插入的数据。

【讨论】:

  • 感谢您的意见。其实我不得不同意 sql server 批量导入不是很复杂。不仅是导入,数据的转换也是残酷的。这样的商业产品真是太可惜了。无论如何,使用单列临时表的技巧似乎是一种常见的做法。一位同事告诉我同样的事情。不过我犹豫是否这样做,因为我害怕对性能产生负面影响!
  • 我没有很多关于预处理BULK INSERT 这样的指标。如果它只是导致问题的文件末尾的一行,您可能需要考虑制作一个小型控制台实用程序来查找文件中的最后一行并将其删除。这样一来,您就可以将一些内容打包到自动上传过程中。
  • 这实际上是我最终做的。虽然不是很迷人!所有这些麻烦都是由于两个程序、SAP 和 SQL Server 的不足造成的。我想知道哪个产品更糟糕? (我个人会投票给 SAP。)
  • SQL其实很方便,但我认为它更侧重于内部数据处理,让程序员开发自己的数据导入和导出接口。
【解决方案2】:

我遇到了同样的麻烦,但是使用 bcp 命令行问题解决了,它根本不占用最后一行

【讨论】:

  • 嗨,欢迎来到 stackoverflow。请详细描述答案。明确的答案将帮助人们理解您的意思,并增加选择作为答案的机会
【解决方案3】:

我遇到了同样的问题。我有一个包含 1150 亿行的文件,因此无法手动删除最后一行,因为我什至无法手动打开该文件,因为它太大了。

我没有使用 BULK INSERT 命令,而是使用了 bcp 命令,如下所示: (在管理员中打开一个 DOS cmd 然后写入)

bcp DatabaseName.dbo.TableNameToInsertIn in C:\Documents\FileNameToImport.dat -S ServerName -U UserName -P PassWord

据我所知,它与批量插入的速度差不多(导入数据只花了我 12 分钟)。在查看活动监视器时,我可以看到批量插入,所以我猜它在数据库处于批量恢复模式时以相同的方式记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多