SQL Server 批量插入是事务性的吗?
Posted
技术标签:
【中文标题】SQL Server 批量插入是事务性的吗?【英文标题】:Is SQL Server Bulk Insert Transactional? 【发布时间】:2010-09-07 16:45:40 【问题描述】:如果我在 SQL Server 2000 查询分析器中运行以下查询:
BULK INSERT OurTable
FROM 'c:\OurTable.txt'
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t', ROWS_PER_BATCH = 10000, TABLOCK)
在符合 OurTable 架构的 40 行文本文件中,但随后更改了最后 20 行的格式(假设最后 20 行的字段较少),我收到错误消息。但是,前 40 行已提交到表中。我调用 Bulk Insert 的方式是否使其不是事务性的,或者我是否需要做一些明确的事情来强制它在失败时回滚?
【问题讨论】:
【参考方案1】:尝试将其放入用户定义的事务中,看看会发生什么。实际上它应该像你描述的那样回滚。
【讨论】:
【参考方案2】:BULK INSERT
充当一系列单独的 INSERT
语句,因此,如果作业失败,它不会回滚所有已提交的插入。
但是,它可以放在事务中,这样您就可以执行以下操作:
BEGIN TRANSACTION
BEGIN TRY
BULK INSERT OurTable
FROM 'c:\OurTable.txt'
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t',
ROWS_PER_BATCH = 10000, TABLOCK)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
【讨论】:
如果要插入大量行,请注意事务日志被填满等情况。【参考方案3】:如 MSDN 库 (http://msdn.microsoft.com/en-us/library/ms188365(v=sql.105).aspx) 中 BULK INSERT 的 BATCHSIZE
定义所述:
“如果失败,SQL Server 会为每个批次提交或回滚事务...”
总之,没有必要为批量插入添加事务性。
【讨论】:
【参考方案4】:您可以回滚插入。要做到这一点,我们首先需要了解两件事
BatchSize
:每个事务要插入的行数。默认是完整的 数据文件。所以一个数据文件在事务中
假设您有一个包含 10 行和第 8 行的文本文件,第 7 行包含一些无效的详细信息。当您在不指定或指定批量大小的情况下批量插入文件时,十分之八的文件会插入到表中。无效行,即第 8 和第 7 行失败并且没有被插入。
发生这种情况是因为默认 MAXERRORS
计数是每笔交易 10 个。
根据 MSDN:
最大错误数:
指定数据中允许的最大语法错误数 在取消批量导入操作之前。每一行都不能 由批量导入操作导入的被忽略并计为一个 错误。如果不指定 max_errors,则默认为 10。
所以为了使所有 10 行都失败,即使其中一个无效,我们需要设置 MAXERRORS=1
和 BatchSize=1
这里 BatchSize 的数量也很重要。
如果您指定 BatchSize 并且无效行在特定批次内,它将仅回滚特定批次,而不是整个数据集。 所以在选择这个选项时要小心
希望这能解决问题。
【讨论】:
使用 BatchSize=1 而不是单独的 INSERT 语句有什么意义? 我认为批量大小 =1 提交的事务与单个插入语句相同,但后者需要一些循环和行号才能插入而不重复。同意您的说法,但可以在 BULK INSERT 属性的帮助下完成以上是关于SQL Server 批量插入是事务性的吗?的主要内容,如果未能解决你的问题,请参考以下文章