2012-07-02 56 views
3

我必须导入SAP未兑换的列表。这些报告看起来相当难看,并不适合自动化处理。但是没有其他选择。SQL SERVER批量插入忽略变形行

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 

不幸的是我收到follwing错误代码:

数据是围绕类似于下面的例子中减去和管道符号borderd
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)". 

拒绝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> 
+0

当我使用具有固定列宽的格式文件(CharFixed而不是CharTerm)时,我发现更好的支持。然后,您可以在where子句中检查预期内容的某些列。但是,由于SAP会改变列的宽度,所以在我的用例中这不是一个选项。 – Toby

+0

很遗憾地看到,SQL Server似乎无法处理并非100%符合所提供格式的行。为什么不能忽略并记录行,然后继续而不是立即中止整个导入。更糟糕的是,一种错误文件被创建,并且只要存在一个错误文件(不会被用户或外部程序删除),就不能再启动了!专业软件不是那种奇怪的行为吗? – Toby

回答

5

BULK INSERT是出了名繁琐的和无益的,当涉及到处理不符合规定的规格数据。

我没有做很多与格式文件的工作,但你可能想一件事作为替代使用BULK INSERT到文件的每一行放入临时分段表单nvarchar(max)列考虑。

这可以让你的数据进入SQL进一步检查,然后你可以使用各种字符串操作函数将它分解成你想要最终插入的数据。

+0

感谢您的意见。其实我必须同意,SQL Server批量导入不是很复杂。而不仅仅是导入,而且数据转换是残酷的。这样的商业产品真是太可惜了。 无论如何,用一个列临时表的伎俩似乎是一种常见的做法。一位同事告诉过我同样的事情。 虽然我很犹豫,但我担心会对性能造成负面影响! – Toby

+0

我没有很多像这样预处理'BULK INSERT'的指标。如果它只是引起问题的文件末尾的一行,则可能需要考虑制作一个小型控制台实用程序,以便在文件中查找最后一行并将其修剪掉。这样你就可以将自己的东西包装到自动上传过程中。 – lyrisey

+0

这实际上是我最终做的。虽然不是很迷人!所有这些只是由于程序,SAP以及SQL Server的不足而造成的麻烦。我想知道哪种产品更差? (我个人会投票给SAP。) – Toby

0

我是在同样的麻烦,但使用BCP命令行的问题解决了,它干脆不走最后一排

+1

嗨,欢迎来到stackoverflow。请更多地描述答案。明确的答案将帮助人们理解你的意思,并增加选择答案的机会 –

0

我有同样的问题。我有一个115亿行的文件,所以手动删除最后一行不是一个选项,因为我无法手动打开文件,因为它太大了。

而不是使用BULK INSERT命令,我用BCP命令,它看起来像这样: (打开在管理员DOS CMD然后写)

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

这是大致相同的速度批量插入远据我所知(只需12分钟导入我的数据)。在查看活动监视器时,我可以看到一个批量插入,所以我猜测它在数据库处于批量恢复模式时以相同的方式记录。