0

私のSQLはあまり良くないと言って、この質問の前に置きます:)

2つの冗長テーブルを使用して、SQLでダブルバッファ実装を構築しようとしています。いつでも、テーブルの1つがアクティブで、もう1つは非アクティブです。テーブルには、データの再読み込み後に切り替えるビューからアクセスします。リロードするときは、非アクティブなテーブルで操作を実行し、完了時にアクティブなキャッシュを切り替えます。

次のようなコードがたくさんあります。

IF @activeCache = 0
   BEGIN WORK ON TABLE 1 AS IT IS INACTIVE
ELSE
   BEGIN WORK ON TABLE 0 AS IT IS INACTIVE

問題は、角かっこの間のコードが簡単ではないため、操作対象のテーブルだけが異なるコードを複製することになります。テーブルパラメータが役立つかもしれないと思いましたが、それらに挿入することはできません(これを行う必要があります)。今の私の唯一のアイデアは、T4テンプレートを使用してクラッドを生成することですが、データベースプロジェクトでそれらを機能させることができないようです。

私たちを助けることができるSQL構造はありますか?可能であれば、動的SQLは使用しないでください。

4

3 に答える 3

2

CREATE SYNONYMオブジェクトの永続的なエイリアス(または、必要に応じて「同義語」)を効果的に作成するために使用できます。ロジックを1回実行して、ターゲットとするテーブルを決定してから、次を実行できます。

CREATE SYNONYM WorkingTable FOR Table1
CREATE SYNONYM MainTable FOR Table2

次に切り替えるには:

DROP SYNONYM WorkingTable
DROP SYNONYM MainTable
CREATE SYNONYM WorkingTable FOR Table2
CREATE SYNONYM MainTable FOR Table1

また、スクリプト内の他のすべての場所で、WorkingTable更新とMainTable読み取りを参照できます。

そうは言っても、これが最善の働き方であるかどうかを問う他のコメント/回答に同意します。

于 2013-02-28T13:29:00.270 に答える
1

2つのテーブルを使用してビューを切り替える代わりに、メインテーブルとステージングテーブルを使用します。

データをメインテーブルに移行する準備ができたら、そのようなアトミックトランザクションで移行できます。

begin try
 begin tran
 delete * from MainTable with (tablockx)
 insert MainTable
 select * from StagingTable with (tablockx)
 commit

end try
begin catch
 rollback
 raiserror('An error occurred swapping staging data', 16,16)
end catch

そうすれば、常にステージングテーブルで作業するため、使用する正しいテーブルを特定するのに問題はありません。

データによっては、メインテーブルの増分更新を実行する場合があります。

-- delete rows which no longer exist
delete MainTable 
from MainTable
where not exists (select 1 from StagingTable where StagingTable.primaryKey = MainTable.primaryKey)

-- Insert new rows
insert MainTable 
select * 
from StagingTable
where not exists (select 1 from MainTable where StagingTable.primaryKey = MainTable.primaryKey)


-- update rows which have changed
update MainTable 
set  
   col1 = stagingTable.col1,
   col2 = stagingTable.col2
from MainTable inner join StagingTable on  StagingTable.primaryKey = MainTable.primaryKey
where 1=2
   -- Need to compare every column, only update if one is different
   -- Both null counts as the same - compare nullity 
   OR case when MainTable.col1 is null then 0 else 1 end <> case when StagingTable.col1 is null then 0 else 1 end
   OR MainTable.col1 <> StagingTable.col1
   OR case when MainTable.col2 is null then 0 else 1 end <> case when StagingTable.col2 is null then 0 else 1 end
   OR MainTable.col2 <> StagingTable.col2
于 2013-02-28T12:44:57.483 に答える
1

@activeCacheをパラメーターとして受け取るインラインテーブル値関数を作成できます。その関数のパラメータに従って、適切なテーブルからすべてのデータを選択します。TIはパフォーマンスについてよくわかりません。

于 2013-02-28T13:07:26.593 に答える