【问题标题】:CSV import to SQL ServerCSV 导入 SQL Server
【发布时间】:2018-12-05 19:22:08
【问题描述】:

我有一个包含 29,471 行的 CSV 文件 (shrlgpa.csv)。但是,当我将其导入 SQL Server 时,输出显示复制了 29,482 行。为什么会这样?

这是我使用的脚本,该脚本适用于所有其他 csv 文件:

USE master
GO
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE WITH OVERRIDE
GO

USE [VCC_BE_SQL_stg]
GO

DECLARE @cmd varchar(8000)
= CONCAT( '"C:\Program Files\Microsoft SQL Server\110\Tools\Binn\bcp.exe"'
    , ' VCC_BE_SQL_stg.VCC.{tbl} in C:\VCCBanner\{tbl}.csv'
    , ' -a 65535 -b 10000 -c -F 2 -U mssql_stg -P password2012 -S'
    , ' WIN-8I8OQB38II4\SQLEXPRESS2012 -t 0x7C -r 0x0A -E'
    )

DECLARE @tables TABLE ( tbl varchar(255) PRIMARY KEY )
INSERT INTO @tables VALUES ('shrlgpa');

DECLARE @tbl varchar(255) = ( SELECT MIN(tbl) FROM @tables )
DECLARE @nth int = 0
DECLARE @cnt int = ( SELECT COUNT(1) FROM @tables )
DECLARE @sql varchar(255)= N'TRUNCATE TABLE VCC_BE_SQL_stg.VCC.'
DECLARE @run nvarchar(255)
WHILE ( @nth <> (@cnt) )
BEGIN
        SET @tbl = (
            SELECT tbl
            FROM @tables
            ORDER BY tbl
            OFFSET @nth ROWS
            FETCH NEXT 1 ROWS ONLY
        )
        --SET @SQL = (SELECT N'TRUNCATE TABLE VCC_BE_SQL_stg.VCC.' + @tbl)
        SET @run = ( SELECT @sql + @tbl )
        select @run
        EXEC sp_executesql @run
        SET @run = ( SELECT REPLACE( @cmd, '{tbl}', @tbl) )
        select @run
        EXEC xp_cmdshell @run
        SET @nth = @nth + 1
END

我已经检查了字段的名称和数量,但我看不出有什么问题,尤其是它与其他文件完美配合

【问题讨论】:

  • 这不是sql问题。我相信 csv 文件有空行。在 excel 或记事本中打开它并按 CTRL + END 我想你会看到问题。
  • @ZekiGumus,只有一个空行,删除它,结果相同
  • 如果没有违规 CSV 的副本,以及(在极端情况下)表定义和所有相关触发器,我们可能会追尾。
  • 如果没有足够的信息来重现问题,就无法诊断。
  • 感谢大家的回答。问题是 csv 文件的路径,我猜我有点累,我没有注意到我正在从备份中编辑 csv 文件,而不是位于脚本路径中的那个。源文件的空行很少,这就是行数不正确的原因

标签: sql sql-server csv


【解决方案1】:

这是我将遵循的调试步骤。

  1. 我会高度怀疑数据文件本身。你 从记事本或 NotePad++ 打开 CSV 看是否有 最后提取行?我会先看看那里并放置你的 光标在最后一个数据行的最后一个值上并按住 shift 键,然后突出显示并删除之后的任何内容。

    1. 如果这仍然导致更多行,那么您应该再次查看该文件。这可能是 CSV 中的数据在文件中带有逗号的结果。文件文本是否合格?含义是用双引号括起来的数据。

    2. 前进的最佳方式是研究如何提取数据。垃圾进垃圾出。如果您的数据文件格式不正确,它会一直困扰着您并且一直是个问题。

祝你好运!

【讨论】:

  • 一般情况下,如果文件不合格,导入过程会立即崩溃,因为到行尾时不会有正确的列数。
  • 但在现实世界中,数据文件会完全加载,最终导入的数据会发生偏移。您不会总是遇到硬错误。
【解决方案2】:

标准错误去哪儿了?也就是说,您在哪里查找来自 bcp.exe 的错误消息?

您正在做的事情——使用动态 SQL 执行命令行实用程序来加载数据库——非常糟糕。如果文件与服务器位于同一台机器上(或可通过文件服务器访问),您可能需要查看BULK INSERT

没有使用 bcp.exe 在面对错误时是健壮的,也就是说它对于批处理编程毫无用处。一方面,当行加载失败时它不会返回错误状态,这意味着调用者在不解析标准错误输出的情况下无法检测到任何问题。另一方面,根据错误的性质,单独或批量删除行。

毫无疑问,在您的情况下发生的是某些行不符合您的希望和期望,并且被 bcp.exe 拒绝(而不是被服务器拒绝,它永远不会看到它们)。一个明显的问题可能是引用的 CSV 字段"like, this",bcp.exe 会将其解释为两个字段,因为它没有引用的概念。被拒绝的行非常详细地报告标准错误。您的挑战是找到并检测错误报告。

一旦你这样做了,你就会发现CSV + BCP = 失败。如果您对 CSV 文件有 绝对 控制权,那么我建议您不要使用可以出现在普通英文散文中的字符作为分隔符,例如逗号。例如,使用制表符,因此没有人认为您拥有一个包含所有复杂性的 CSV 文件。

如果您不控制输入文件的格式,请不要使用 bcp.exe 加载它。首先使用一个工具将其解析为 CSV 文件,该工具解释了各种可怕的 CSV 语法,并生成一个由制表符或其他严格分隔的文件,bcp.exe 不会出错。然后加载它。

如果您真的想深入研究它,FreeTDS 项目包含一个实用程序freebcp,它确实返回错误状态并且可以可靠地批量使用。不过,我最后看了一下,你必须先编译它;它仅作为源代码分发。

【讨论】:

  • 感谢您的详细解答。问题很愚蠢....我正在编辑备份 csv 而不是脚本路径中的那个
猜你喜欢
  • 2011-03-19
  • 2021-02-04
  • 2012-04-05
  • 2014-01-02
  • 2013-02-20
  • 2011-04-01
  • 2014-10-29
  • 2013-10-08
相关资源
最近更新 更多