8

我正在使用 XML 格式文件导入 CSV 文件,并且第一个数据行被跳过。我不知道为什么。

格式化文件

<?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="1" xsi:type="CharTerm" TERMINATOR='","' />
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR='\n' />
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="COLUMN1" xsi:type="SQLVARYCHAR" />
  <COLUMN SOURCE="2" NAME="COLUMN2" xsi:type="SQLVARYCHAR" />
 </ROW>
</BCPFORMAT>

CSV

COLUMN1,COLUMN2
"ABC","ABC123456"
"TNT","TNT123456"

询问

SELECT *
FROM OPENROWSET(BULK 'C:\sample.csv',
FORMATFILE='C:\sample.xml',
FIRSTROW = 2) AS a

结果

COLUMN1 COLUMN2
------- ----------
"TNT    TNT123456"

(1 row(s) affected)

如果FIRSTROW改为1,结果变为:

COLUMN1                COLUMN2
---------------------  ----------
COLUMN1,COLUMN2  "ABC  ABC123456" 
"TNT                   TNT123456"

如果标题行从 CSV 中删除并FIRSTROW更改为1,则结果按预期返回:

COLUMN1 COLUMN2
------- ----------
"ABC    ABC123456" 
"TNT    TNT123456"

由于这是一个带有标题的自动报告,是否有任何其他选项可以解决这个问题?

4

6 回答 6

3

这里有几个问题:

  1. \n我怀疑第一行没有有效的。否则,当您更改为FIRSTROW = 1.

  2. 用作","列分隔符对除第一列和最后一列之外的所有列都有效。这会在第一列留下前导,在最后一列留下"尾随"。您可以通过更改ROWTERMINATORto来处理后者"\n,但这只有在您还可以"在标题行中添加尾随(在确保那里有效的过程中\n)时才有效。此时,您不妨确保标题行在所有方面都与数据行匹配,因此:

    "COLUMN1","COLUMN2"
    -------------------^ this character has to be \n
    

老实说,我认为您可以花一周时间与所有这些细节BCPBULK INSERT问题作斗争,但仍然没有不需要后期操作的完美解决方案(例如"从某些列中修剪前导/尾随字符) . 我的建议:花 20 分钟用 C# 编写一个解析器,它会自动更正这些文件 - 删除标题行,确保正确的分隔符到位,删除所有愚蠢的",等等,然后 SQL Server 才能看到文件。清理文件将比您现在跳过的麻烦少得多。我敢肯定有解决方案,但IIRC你一直在努力解决它很长一段时间......

于 2013-09-11T20:50:04.687 回答
2

第一个字段的终止符只能是',',而不是'","'。

替换为以下行,它将起作用:

<FIELD ID="1" xsi:type="CharTerm" TERMINATOR=',' />

这是您的原始文件格式会发生什么...

第一列以 : ","... 结尾,这意味着 SQL 服务器解析第一行,然后读取第二行并获取第一个字段:

COLUMN1,COLUMN2  "ABC

它继续读取并获取第二个字段(请记住,我们仍在文件的第二行):

ABC123456"

它现在有第一行...

然后它读取下一行:

"TNT                   TNT123456"

因此,当您跳过第一行时,它确实会跳过第一行,因为您的第一行没有使用引号......

希望有帮助..

于 2013-09-11T20:36:03.463 回答
1

另外,请检查 .CSV 文件的字符编码。它可能是带有三字节签名的 UTF-8。bcp.exe 似乎不理解这种格式。确保您的文件以单字节 ASCII 格式保存。您也可以尝试指定 UTF-8 代码页参数 ( -C 65001 ),但 AFAIR 它不适用于某些较旧的 SQL 服务器版本。

编辑:当导入为带有 UTF-8 签名的 .csv 文件时,我观察到同样的问题:第一个数据行(带有签名的行)被跳过。

于 2015-01-19T20:14:12.823 回答
0
<?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="1" xsi:type="CharTerm" TERMINATOR="\""/>
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR="\",\"" />
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR="\"\r\n"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="2" NAME="COLUMN1" xsi:type="SQLVARYCHAR" />
  <COLUMN SOURCE="3" NAME="COLUMN2" xsi:type="SQLVARYCHAR" />
 </ROW>
</BCPFORMAT>

此处提供的 BCP 格式文件将有助于跳过第一个字段,该字段本质上可以忽略 COLUMN1 值上的开头“。记录上的 FIELD1 以单双引号终止并将被跳过。Field2 由双引号终止后跟逗号,后跟双引号 \",\"(此处的反斜杠用于转义双引号字符)。Field3 以双引号结尾,后跟 CR(回车),然后是 LF(lineFeed),即\"\r\n.

系统读取第一个字段直到双引号并跳过它,读取第二个字段直到 \",\" 并将其分配给 COLUMN1,读取第三个字段直到 \"\r\n 并分配给 COLUMN2 并移动在下一条记录上等等。基本上这应该对您的 CSV 文件提要有效。

于 2013-11-02T16:16:00.137 回答
0

在 XML 格式文件中放入一个false字段"0",但不要映射任何其他列。

<FIELD ID="0" xsi:type="CharTerm" TERMINATOR='"' />

使用以下查询对我有用:

SELECT  * FROM OPENROWSET( BULK 'C:\sample.txt', FIRSTROW = 0,
   FORMATFILE = 'C:\sample.xml' ) AS a;
于 2014-12-04T21:53:57.363 回答
0

我遇到了完全相同的问题,CSV 数据的标题也需要有双引号(即使您在 BCP 或批量插入时尝试跳过第一行,这也令人难以置信)或者您只需删除标题(您的第一行CSV 文件):

"COLUMN1","COLUMN2" "ABC","ABC123456" "TNT","TNT123456"

于 2016-04-30T00:27:57.923 回答