在sql中提交每个x记录

时间:2015-04-19 14:46:10

标签: sql-server tsql

我来自oracle背景,我对SQL Server感到困惑。

我想在insert命令中阻止SQL Server自动提交。所以我使用的是begin transaction。在下面的演示中,我将100行插入测试表中,并且我将在事务结束时回滚。我期待的结果是90行(提交应该是30,60和90行),其余10条记录应该回滚。

CREATE TABLE test (TEST_ID INT);
GO

DECLARE @cnt INT=0;
BEGIN TRANSACTION t1;

WHILE @cnt < 100
BEGIN
  INSERT INTO test values (@cnt); 
  SET @cnt += 1;

  if (@cnt %30 = 0)
    print 'commit '+cast(@cnt as varchar(100))
    COMMIT TRANSACTION t1;
END

rollback transaction t1;
GO

首先,我确保关闭了SQL Server Management Studio自动提交,因为我遵循以下步骤:

Tools > Option > Query Execution > Sql Server > Ansi > checked the SET IMPLICIT_TRANSACTION

之后我运行了脚本,但是我得到了错误的结果,并且出现了一些错误。

  

ROLLBACK TRANSACTION请求没有相应的BEGIN TRANSACTION。

,行数为100!

我试图关闭我的连接并在oracle中再次打开它,当我插入时说100行而不提交最后说10行,其他人可以看到90行,但是我看到了100行,因为它是已保存在我的会话中。但看起来SQL Server在会话和事务方面的行为方式不同。

我遇到的另一个问题是关于while循环内部的提交,看起来它无法访问循环中的begin事务。当我运行命令时,我没有选择任何东西。只需按f5。即使我尝试了选择命令并运行但仍然给了我错误:

  

COMMIT TRANSACTION请求没有相应的BEGIN TRANSACTION。

我对SQL Server感到疯狂,我可以使用mysql和oracle轻松工作,但SQL Server ....

3 个答案:

答案 0 :(得分:4)

实际上Sql Server不支持嵌套事务。它将允许您开始嵌套事务,但不允许在此处和那里回滚。实现此目的的唯一方法是使用save transaction语句。您可以在循环中向事务添加一些保存点,然后在外部循环中您可以回滚到该保存点并提交事务。这是一个例子:

DECLARE @cnt INT=0
Begin transaction

WHILE @cnt<100
BEGIN
  INSERT INTO test values (@cnt)
  SET @cnt+=1

  if (@cnt%30=0)
  begin
      save transaction t1
  end
END;

rollback transaction t1;
commit;

Select * from test

输出为0到89。

这是小提琴http://sqlfiddle.com/#!6/07af4/37

答案 1 :(得分:0)

分号没有你期望的效果。尝试更改此部分:

if (@cnt%30=0)
    BEGIN
        print 'commit '+cast(@cnt as varchar(100))
        COMMIT TRANSACTION t1
    END --IF @cnt
END --WHILE @cnt

答案 2 :(得分:0)

您的代码在WHILE循环之外启动单个事务,尝试提交100次然后尝试回滚。 100你说?您的IF语句没有BEGIN / END来控制复合语句。 PRINT将被执行三次,但COMMIT将执行100次。

单个事务不能多次提交(或回滚),因此错误。您可以提交一个事务,然后在IF内启动另一个事务,但这会将回滚限制为仅插入的最后一行。通常,您将启动事务,执行所有插入,然后提交或回滚。

除此之外:SQL Server中的嵌套事务没有按照您的想法执行。有关详细信息,请参阅here