2013-02-28 133 views
0

我會說我的SQL前言這個問題不太好:)避免代碼重複在SQL

我們正試圖通過具有2個冗餘表來建立SQL中的雙緩衝的實現。在任何一個時間,其中一個表是活動的,另一個是非活動的。這些表格通過我們在重新加載數據後切換的視圖進行訪問。當我們重新加載時,我們希望在非活動表上執行操作,然後在完成時切換活動緩存。

我們有大量的代碼,看起來有點像:

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。

+0

[DBA網站上的相關問題](http://dba.stackexchange.com/q/33470) – 2013-02-28 13:09:09

回答

2

您可以使用CREATE SYNONYM爲對象有效創建永久性別名(或「同義詞」,如果您願意的話)。你可以運行你的邏輯,一旦確定要定位哪個表,然後運行:

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進行讀取。

這就是說,我同意其他評論/回答質疑這是否是最好的工作方式。

1

而不是使用兩個表並切換視圖,使用主表和臨時表。

當您準備將數據遷移到主表時,您可以像這樣在原子事務中執行此操作。

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 
+0

+1用於避免2表的想法。從桌面切換到桌面聽起來像是壞消息......如果某件事在你的代碼中途失敗了,該怎麼辦?如果你想要兩個表具有相同的數據,你應該使用複製,跨多個服務器或類似的負載平衡。 – twoleggedhorse 2013-02-28 12:47:11

+0

謝謝,我看到的唯一問題是需要很長時間來切換,因爲我們清空主表並重新填充它意味着它將在其持續時間下降,從而失去了「雙緩衝」的目的 – moosecode 2013-02-28 13:01:00

+0

@moosecode首先,你有沒有計時?這實際上是一個問題,還是僅僅是一種理論?使用'TABLOCKX'將極大地加快速度。你也研究過未記錄的操作,這也應該更快?其次,第二個選項會起作用嗎?其他用戶可能看到部分更新的數據。這可能或不是問題取決於數據和他們在做什麼。 – Ben 2013-02-28 13:10:24

1

您可以創建內嵌表值函數,它接受@activeCache作爲參數。根據該函數中的參數選擇適當表中的所有數據。我不確定表現。