sql - 这将如何影响使用带有回滚事务的循环的数据

标签 sql sql-server tsql stored-procedures rollback

While @@Fetch_Status = 0
Begin
    INSERT INTO  [server].MyDatabase.dbo.Mytabletobeinserted (

    UPC,
    Sale_date)  
    VALUES(
    @UPC,
    @Sale_date)

    'Inserting the error trapping here'

    IF (@@ERROR <> 0)
    BEGIN
        ROLLBACK TRANSACTION;
        RETURN;
    END 

    Update t_sale_from_pos
    set been_sent = 'y' 
    where UPC = @UPC and sale_date=@sale_date

    Fetch Next from CursorSale
    into 
    @UPC,
    @Sale_date
end
close CursorSale

deallocate CursorSale

此存储过程每天都会通过调度程序运行,并且数据通过网络传递。当该存储过程执行时,然后在执行过程中会突然出现网络超时。这会执行每一行以通过网络发送到其他服务器。

<小时/> 现在,我的问题是:

  • 这将如何影响循环内调用回滚事务的数据?
  • 它会再次读取所有行并将其发送到服务器进行插入,还是只会读取执行期间失败的行?

需要一些建议。谢谢

最佳答案

你可以尝试begin distributed transactionDistributed transaction在这种情况下是完美的选择,因为分布式事务被设计为跨越两个或更多服务器。通过事务,即使系统崩溃,或者断电,系统仍然能够恢复到一致的状态。

BEGIN DISTRIBUTED TRANSACTION;

BEGIN TRY
    //Your code here to create the cursor.
    While @@Fetch_Status = 0
    Begin
         INSERT INTO  [server].MyDatabase.dbo.Mytabletobeinserted(UPC,Sale_date)  
                                                          VALUES(@UPC,@Sale_date)

         Update t_sale_from_pos
         set been_sent = 'y' 
         where UPC = @UPC and sale_date=@sale_date

         Fetch Next from CursorSale into @UPC,@Sale_date
    END
    close CursorSale

    deallocate CursorSale
END TRY
BEGIN CATCH
    close CursorSale

    deallocate CursorSale

    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

实际上,对于分布式事务,您不需要使用游标。对于您的情况,最好还考虑通过创建临时表来避免并发问题。原因是:插入语句可能需要时间,并且在插入数据时,您的表可能会被其他用户更新,而之后发生的更新语句可能会更新错误的行。

BEGIN DISTRIBUTED TRANSACTION;

BEGIN TRY
    CREATE TABLE #LocalTempTable(UPC int,Sale_date datetime)
    INSERT INTO #LocalTempTable(UPC,Sale_date)
    SELECT UPC,Sale_date 
    FROM YourTable

    INSERT INTO [server].MyDatabase.dbo.Mytabletobeinserted(UPC,Sale_date)  
    SELECT UPC,Sale_date 
    FROM #LocalTempTable

    Update t_sale_from_pos
    set been_sent = 'y' 
    where EXISTS (SELECT *
                  FROM #LocalTempTable
                  WHERE #LocalTempTable.UPC = t_sale_from_pos.UPC 
                        AND #LocalTempTable.Sale_date  = t_sale_from_pos.Sale_date)

END
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

关于sql - 这将如何影响使用带有回滚事务的循环的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17159792/

相关文章:

php - (PHP) 我的数组中有未知数量的键值对,如何在 SQL 查询中使用它们?

sql - 将前 1000 条记录从 csv 文件导入到 sql server

mysql - 使用子选择和分组进行排序

sql - 这两个查询在获得两个不同的结果集时有什么区别?

sql - SQL Server 中的父子关系

mysql - 按名称 desc 分组 - 获取分组名称的最后输入值

java - 使用临时表的有效 SQL 不返回任何结果集

sql - 如何使用表变量作为 OPENQUERY 的参数

asp.net - 将静态数据存储在数据库或文件系统中

mysql - 将数据从 mssql 复制到 mysql 的最佳工具