【问题标题】:commit every x record in tsql提交 sql 中的每条 x 记录
【发布时间】:2015-04-19 14:46:09
【问题描述】:

我来自 oracle 背景,我对 SQL Server 有点困惑。

我想阻止 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!

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

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

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

我对 SQL Server 越来越着迷了,我可以用 mysql 和 oracle 轻松地工作,但是 SQL Server ....

【问题讨论】:

  • 这非常简单,真的:一旦您开始 一个事务 (T1),它就会一直存在,直到您调用 COMMITROLLBACK 为止。因此,一旦您插入 30 行并调用 COMMIT - 然后 transaction T1 已完成 并完成。时期。 T1 周围不再有交易 - 那么下次当您致电 COMMIT T1ROLLBACK T1 时您会期待什么?!?!? 没有交易
  • @marc_s,感谢您的编辑,正如 Giorgi Nakeuri 所写,我需要保存交易而不是提交

标签: sql-server tsql


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    分号没有达到您期望的效果。尝试更改这部分:

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

    【讨论】:

      【解决方案3】:

      您的代码在WHILE 循环之外启动一个事务,尝试提交它 100 次,然后尝试回滚。你说100?您的 IF 语句没有 BEGIN/END 以使其控制复合语句。 PRINT 会执行三次,而COMMIT 会执行 100 次。

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

      除此之外:SQL Server 中的嵌套事务不会按照您的想法进行。请参阅here 了解更多信息。

      【讨论】:

      • 抱歉,我后来添加了 print 以测试我的提交是否在正确的位置,最初它不存在。如果我删除打印我得到提交错误,看起来它看不到T1
      • 无论您尝试提交单个事务 100 次还是 3 次,这仍然太多。一次就是你得到的。
      猜你喜欢
      • 1970-01-01
      • 2017-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2020-12-15
      相关资源
      最近更新 更多