避免在sql中重复代码

时间:2013-02-28 12:40:00

标签: sql sql-server tsql t4

我将通过说我的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模板为我们生成crud,但我似乎无法让它们在数据库项目中工作。

有没有可以帮助我们的sql构造?如果可能的话,我们宁愿不使用动态的SQL。

3 个答案:

答案 0 :(得分: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 :(得分: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

答案 2 :(得分:1)

您可以创建内联表值函数,该函数将@activeCache作为参数。根据该函数中的参数从正确的表中选择所有数据。 TI对性能不确定。