从CSV文件批量插入 - 跳过重复项

时间:2014-12-15 13:15:49

标签: sql sql-server csv bulkinsert sql-server-2014

UPDATE:使用Johnny Bubriski创建的此方法结束,然后稍微修改它以跳过重复项。像魅力一样,显然非常快。 链接:http://johnnycode.com/2013/08/19/using-c-sharp-sqlbulkcopy-to-import-csv-data-sql-server/

我一直在寻找这个答案,但似乎无法找到它。我正在进行T-SQL批量插入,以便从csv文件将数据加载到本地数据库的表中。我的陈述如下:

BULK INSERT Orders
FROM 'csvfile.csv'
WITH(FIELDTERMINATOR = ';', ROWTERMINATOR = '0x0a', FORMATFILE = 'formatfile.fmt', ERRORFILE = 'C:\\ProgramData\\Tools_TextileMagazine\\AdditionalFiles\\BulkInsertErrors.txt')
GO

SELECT * 
FROM Orders
GO

当我尝试插入重复的行时(例如,将相同的csv文件两次),这会导致整个插入停止和回滚,从而出现异常。我可以理解,因为我违反了主键约束。现在我只是显示一个消息框,让用户知道csv文件中存在重复项,但这当然不是一个合适的解决方案,实际上根本不是解决方案。我的问题是,有没有办法忽略这些重复的行,只是跳过它们,只添加不重复的行?或许以某种方式尝试捕捉?

如果不可能,那么"正确" (因为没有更好的词)从csv文件导入数据的方法?这个例外让我有点麻烦。我确实在某处读过你可以设置临时表,将数据加载到其中并在插入之前在两个表之间选择不同的表。但是批量插入真的没有更简单的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以将MAXERRORS属性设置为相当高的值,这将允许插入有效记录并忽略重复项。不幸的是,这意味着数据集中的任何其他错误都不会导致负载失败。

或者,您可以设置BATCHSIZE属性,该属性将在多个事务中加载数据,因此如果存在重复项,则只会回滚批处理。

更安全但效率更低的方法是将CSV文件加载到单独的空表中,然后将它们合并到您提到的订单表中。就个人而言,这就是我的方式。

这些解决方案都不是理想的,但我无法想到忽略批量插入语法中重复的方法。

答案 1 :(得分:0)

首先,没有像BULK INSERT WHERE NOT EXISTS这样的直接解决方案。您可以使用以下解决方案。

使用批量插入时,有两种情况

  1. 您要在一个空表中批量插入
  2. 您要在已填充的表格中批量插入

案例1的解决方案 设置MAXERRORS = 0 设置BATCHSIZE = CSV文件中的总行数

将以上语句与BULK INSERT一起使用将导致整个BULK INSERT操作回滚,即使只有一个错误,这也将防止即使几行中有错误也无法导入行。您将需要解决所有导入错误才能完成导入操作。当您导入50行,导入30行而其余未导入时,此方法将防止出现这种情况。然后,您必须在CSV文件中搜索失败的文件,然后重新导入它们,或从SQL表中删除所有导入的行,然后再次进行大容量插入。

案例2的解决方案: 1>您可以在现有表上运行选择查询,右键单击并以CSV格式导出。如果您有任何电子表格程序,则将数据粘贴到导入数据下方,并在主键列上使用条件格式突出显示重复的行并将其删除。然后使用BULK INSERT操作。

2>设置MAXERRORS =行数,并使用BULK INSERT导入csv文件。这是不安全的建议方法,因为除了重复的键错误外,还有其他错误

3>设置BATCHSIZE = 1并且MAXERRORS = high number,然后使用BULK INSERT导入csv文件。这将导入所有没有错误的行,并且任何有错误的行都将被跳过。如果数据集较小,并且可以通过观察表列(例如显示缺失数字的ID号列)来直观地标识未导入的行,则此功能很有用。

4>右键单击现有表,将表选择为> Crete to>新查询窗口。只需重命名表名称并更改为登台名称(如table_staging)。 BULK插入登台表,然后运行第二个查询以将数据从登台表复制到主表,并使用WHERE子句检查是否存在row / pk。这是一种更安全的方法,但是会迫使您创建临时表。