清除并填充SQL Server中的表

时间:2019-12-20 19:05:11

标签: sql sql-server sql-server-2016

我有一个非常简单且常见的方案:我需要每天更新两个表。它们通常连接在一起,并且仅由用户读取(除我的维护工作外,没有更新发生,这需要几分钟的时间来运行)。

我需要两个表中的数据版本保持同步-它们两者都需要随时具有相同的数据版本。另外,我想尽可能地限制停机时间和锁定,因为在更新过程中可以主动查询表中的数据。最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

没有足够的信息来彻底回答这个问题,但是,我会尽力提供第一遍。建议您使用更多信息来更新您的答案。

假设一个表是只读的,而另一个表不是只读的,则将截断和插入包装在一个事务中的表可能是可行的解决方案。

begin tran
truncate table tableA;
insert into TableA select * from TableB;
commit;

另一种方法是从两个来源获取主键值,对重要的列(差异很重要的列)进行哈希处理,如果特定键上的哈希值不匹配,则更新表。

select primary_key, hashbytes('md5', lower(concat(columna,columnb,columnc))) "hash"
from tableA
except
select primary_key, hashbytes('md5', lower(concat(columna,columnb,columnc))) "hash"
from tableB

另一个选择是识别需要更改的记录(以多种方式,例如使用上面的哈希系统),删除相应的PK并将新记录插入到目标表中,而不是完整的截断。

/* using example code above .... */
delete from tableA where exists (select 1 from TableB where pk = pk and hash <> hash);
insert into tableA select * from TableB where not exists (select 1 from tableA where pk = pk);

答案 1 :(得分:1)

您可以将数据加载到具有不同架构的同名表中,然后将其换出。在这里加载staging.Table1和staging.Table2,然后将它们与dbo中的版本交换。目标表必须为空:

begin transaction
  truncate table dbo.Table1;
  truncate table dbo.Table2;
  alter table staging.Table1 switch to dbo.Table1;
  alter table staging.Table2 switch to dbo.Table2;
commit transaction

我认为交换应该在它自己的事务中,因为它将获取模式锁。您总是可以多次重新加载登台表,并且只要加载成功就可以交换。如果加载表的过程花费一些时间,那么模式锁将干扰查询系统表,例如,如果您打开SSMS并尝试列出对象。