【问题标题】:first data row skipped in import导入时跳过的第一个数据行
【发布时间】:2013-09-16 00:28:25
【问题描述】:

我正在使用 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"

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

【问题讨论】:

  • 好的,所以他有点简洁,但除非我非常愚蠢(而且我对 SQL Server 的内部知识知之甚少,所以这是可能的)我不知道为什么这会被如此多地否决。这是一个有效的问题,具有足够的信息来测试和重现问题。 (我们甚至同意极不寻常的标签)
  • 神圣的不必要的投票旅
  • 您应该添加一些绒毛,使您的问题更加冗长。
  • 这似乎是一个分隔符问题 - 我敢打赌你的标题行没有正确的 \n。此外,任何行中的第一列和最后一列将分别保留前导和尾随"。
  • 对向您发送文件的人大喊大叫 :-)?

标签: sql-server csv import


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 嗨 Stanislav - 欢迎使用 Stack Exchange。理想情况下,您的答案应该是完整的、完整的、独立的。我知道您还不能添加评论,这可能更适合此评论,但对于答案,完整的句子,没有文字和缩写表示赞赏。
    【解决方案3】:

    在 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;
    

    【讨论】:

    • 不知道这种方式先删除一行!
    【解决方案4】:
    <?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 文件提要完全有效。

    【讨论】:

      【解决方案5】:

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

      换成下面这行,就可以了:

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

      您的原始文件格式会发生以下情况...

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

      COLUMN1,COLUMN2  "ABC
      

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

      ABC123456"
      

      它现在有第一行...

      然后读取下一行:

      "TNT                   TNT123456"
      

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

      希望对您有所帮助..

      【讨论】:

      • 如果你这样做,你会得到所有被引用的东西; Aaron 确定的问题是第一个 row 中没有换行符。
      • 虽然这可能有效,但我不想为每列应用REPLACE(其中有 32 个)。
      • FreshPrinceOfSO,你读过我编辑的答案吗?我建议你把你的“标题”列名引用..
      • @Baral 如果您建议对实际数据文件进行某种解析,那不是一种选择,因为这是一种自动交付。
      • @FreshPrinceOfSO 我明白了。那么这里没有奇迹般的解决方案......按照亚伦的建议去做。
      【解决方案6】:

      这里有几个问题:

      1. 我怀疑第一行没有有效的\n。否则,当您更改为 FIRSTROW = 1 时,SQL Server 不会处理前两行。

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

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

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

      【讨论】:

        猜你喜欢
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 2017-09-21
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        相关资源
        最近更新 更多