大容量复制无错误提交行

本文关键字:提交 无错误 复制 大容量 | 更新日期: 2023-09-27 17:59:41

我有一个进程,它使用SQL大容量复制来获取列表并将其插入数据库,因为这个列表可能特别大。它运行良好,检查约束,所有这些都很完美。问题是,如果我有10000条记录,其中一条记录有错误,我仍然想提交另9999条。除了在SQL大容量复制之前手动检查每个约束或一次插入一个约束之外,还有其他方法可以做到这一点吗?看起来乏味而缓慢,这有点不符合要点。谢谢

var copy = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["constr"].ConnectionString, SqlBulkCopyOptions.CheckConstraints)
{ 
    DestinationTableName = obj.TableName 
};
var table = new DataTable();
copy.WriteToServer(table);

大容量复制无错误提交行

如果不将批量大小设置为1(这将破坏大容量复制的目的)或在复制前预检查数据,解决此问题的正常方法是将数据复制到与目标表具有相同架构但没有约束的临时表中,删除在插入时违反约束的行,然后从临时表中正常插入到活动表中。

const string _createTableString = "Create table #temp (/* SNIP */)";
const string _insertTableString = @"
declare @sql nvarchar(2000)
set @sql = N'INSERT INTO ' + QUOTENAME(@tableName) + N' SELECT * from #temp'
exec sp_executesql @sql";
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["constr"].ConnectionString))
{
    connection.Open();
    using (var command = new SqlCommand(_createTableString, connection))
    {
        command.ExecuteNonQuery();
    }
    using (var copy = new SqlBulkCopy(connection))
    {
        copy.DestinationTableName = "#temp";
        copy.WriteToServer(table);
    }
    using (var command = new SqlCommand(_insertTableString, connection))
    {
        command.Parameters.AddWithValue("@tableName", obj.TableName)
        command.ExecuteNonQuery();
    }
}

注意使用QUOTENAME以确保没有SQL注入可以通过传递给obj.TableName的表的名称偷偷进入。