交换ms-sql表

时间:2009-03-03 09:47:30

标签: sql swap

我想以最佳方式交换表格 我有一个IpToCountry表,我根据我导入的外部CSV文件每周创建一个新表。

我发现进行切换的最快方法是执行以下操作:

sp_rename IpToCountry IpToCountryOld
go
sp_rename IpToCountryNew IpToCountry
go

这个问题是桌子之间仍然可以访问 如何在SQL中解决此问题? 考虑使用sp_getapplock和sp_releaseapplock,但我希望尽快保持对表函数的读取。

6 个答案:

答案 0 :(得分:16)

假设您无法更新/插入现有表格,为什么不使用view包装对表格的所有访问权限?

例如,您最初可能将数据存储在名为 IpToCountry20090303 的表中,您的视图将是这样的:

CREATE VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090303

当新数据进入时,您可以创建并填充 IpToCountry20090310 表。填充表后,只需更新您的视图:

ALTER VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090310

交换机将完全是原子的,无需任何显式锁定或事务。视图更新后,您只需删除旧表(或者如果您愿意,可以保留它)。

答案 1 :(得分:1)

实现您希望实现的目标的另一种方法是使用表分区,这是SQL Server企业版中提供的一种技术。

表名可以保持不变。表导入完成后,只需切换出包含旧数据的分区,然后切换到新分区。

以下白皮书包含您开始使用所需的所有信息。

http://msdn.microsoft.com/en-us/library/ms345146.aspx

干杯,约翰

答案 2 :(得分:1)

我在分区功能大规模工作时遇到了问题。 CREATE和DROP PARTITION是阻塞操作,你几乎无法控制阻塞,如果它无法获得锁定,它将以严重级别16失败并终止你的连接 - 你不能陷阱并重新尝试而不重新建立连接。但它可能适合你。此外,MSS企业版是必需的,您不能使用SE - 可能对于一些较小或更具成本关注的商店来说太多了。

我还发现视图redef在sys表和对象上以高规模(=事务量+不断插入的数据的大量数量,在我的情况下)阻塞,因此这些操作可能会在重新索引和DTCC - 在一种情况下,特别是SSMS(所有事物)中的用户试图在对象资源管理器中浏览视图(有人需要告诉那些人有关READPAST)。同样,您的里程可能会有所不同。

相比之下,sp_rename对我来说效果很好:它可以控制锁定及其范围。要解决交换之前的阻塞问题,请尝试如下所示。从表面看,这似乎在高容量时具有相同的规模问题......但我在实践中没有看到它。所以,对我有用......但同样,每个人的需求和经历都是不同的。

DECLARE @dummylock bit 
BEGIN TRANSACTION 
BEGIN TRY
   -- necessary to obtain exclusive lock on the table prior to swapping
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM A WITH (TABLOCKX))
   -- may or may not be necessary in your case
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM B WITH (TABLOCKX))
   exec sp_rename 'A', 'TEMP'
   exec sp_rename 'B', 'A'
   exec sp_rename 'TEMP', 'B'
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   -- other error handling here if needed
   ROLLBACK TRANSACTION 
END CATCH

答案 3 :(得分:0)

IpToCountryOld会发生什么?你扔掉了吗?在这种情况下,为什么不截断IpToCountry并导入我的新数据。

如果您需要保留数据,那么如何将加载日期存储在表中并将“当前”加载日期存储在WHERE子句中的某个位置?然后在成功加载数据时切换当前日期。

你没有说你正在使用哪个数据库,所以我不知道它有多少使用,但你有没有引用该表的存储过程?请注意,在某些平台上,SP使用对表不会随重命名而更改的表的内部引用进行编译,因此存在SP在没有重新编译的情况下不会获取新数据的风险。视图和存储的已解析查询也是如此。

答案 4 :(得分:0)

在下班时间你不能导入到一张桌子吗?

或者为什么不进行数据更新,即更新现有记录并在循环导入数据时逐个记录地添加任何新记录。这将允许表保持活动并减少添加和删除完整表的总体影响。

导入数据的结构,表格设计,格式,PK等是什么?从那以后我们可以给你一个更好的答案。

答案 5 :(得分:0)

刚遇到一个类似的问题,正在使用适当的锁定进行扩展问题的临时表。

您的表被引用的任何地方都可以调用存储过程来询问表名。

存储过程可以选择创建新表或根据提供的参数返回旧表。