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
此存储过程每天都使用调度程序运行,数据通过网络传递。当此存储过程执行时,然后沿着执行过程突然出现网络超时。这将执行每一行以通过网络发送到其他服务器。
<小时/> 现在,我的问题是:
需要一些建议。感谢
答案 0 :(得分:6)
您可以尝试begin distributed transaction。 Distributed 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
实际上,对于分布式事务,您不需要使用游标。在您的情况下,最好还考虑通过创建临时表来避免并发问题。原因是:insert语句可能需要一些时间,当它插入数据时,您的表可能会被另一个用户更新,之后发生的更新语句可能会更新错误的行。
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
答案 1 :(得分:3)
如果我理解正确的话。 TRY / CATCH应该帮助你 -
WHILE @@FETCH_STATUS = 0 BEGIN
BEGIN TRY
INSERT INTO [server].MyDatabase.dbo.Mytabletobeinserted (UPC, Sale_date)
SELECT @UPC, @Sale_date
UPDATE dbo.t_sale_from_pos
SET been_sent = 'y'
WHERE UPC = @UPC
AND sale_date = @sale_date
END TRY
BEGIN CATCH
UPDATE dbo.t_sale_from_pos
SET been_sent = 'n'
WHERE UPC = @UPC
AND sale_date = @sale_date
END CATCH
FETCH NEXT FROM CursorSale INTO @UPC, @Sale_date
END
CLOSE CursorSale
DEALLOCATE CursorSale
答案 2 :(得分:1)
我认为你在错误的地方感到困惑,
此处,0 = The FETCH statement was successful.
因此,在获取成功之前,循环将继续,如果发生任何@@错误,它将以创建的游标中的所有行结束。如果没有发生错误
你在逻辑上是正确的,如果CursorSale
在适当的地方被正确定义,它将正常工作..
有关更多提示请参阅以上链接中的示例
我希望这样做..
答案 3 :(得分:0)
我建议不要循环每条记录,而是以块的形式进行插入。像一次5000条记录一样,如果它是一个自动化的工作,那么这是可行的。
这是我找到的一个链接,但基本上你会在你的循环中每次进行前5000次。我想如果你有一个工作在插入的每个记录上运行游标,它可能会变得非常昂贵。