begin distributed transactionを試すことができます。 Distributed transactionは、分散トランザクションが2つ以上のサーバーにまたがるように設計されているため、この場合に最適です。トランザクションを使用すると、システムがクラッシュしたり、電源が切れても、システムは引き続き一貫した状態に復旧することができます。
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 [email protected]_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文に時間がかかることがあり、データを挿入している間にテーブルが別のユーザによって更新され、その後に発生するupdate文が間違った行を更新する可能性があるためです。
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
カーソルの代わりに、トランザクション内の更新が続くだけ挿入してこれをやっている理由は、特定の理由がありますか? – peterm
このテーブルには何千ものデータが格納されているため、この実行中にサーバがビジー状態にならないように、カーソルを置く必要があります。これは悪い習慣ですか? – Androidz
@Androidz - これは、セットとして行うよりも、データベースにもっと多くの仕事をもたらすでしょう。私の経験では、列のチャンクを行うこの神話的な「ベスト・プラクティス」は、トランザクション・ログと表スペースを適切に管理することができないDBAによって広がっています。 – LoztInSpace