使用新数据和架构安全地替换表

时间:2017-05-23 16:49:23

标签: sql sql-server sql-server-2014

我正在尝试创建一个存储过程,从头开始重新创建一个表,可能会更改架构(包括列的可能添加/删除),方法是使用DROP TABLE后跟SELECT INTO ,像这样:

BEGIN TRAN
DROP TABLE [MyTable]
SELECT (...) INTO [MyTable] FROM (...)
COMMIT

我担心的是,如果有人在删除表之后但在SELECT INTO完成之前尝试访问该表,则可能会产生错误。有没有办法以一种在DROP中持续存在的方式锁定[MyTable]? 我可以DROP/SELECT INTO而不是TRUNCATE/INSERT INTO,但这不允许更改架构。 SELECT INTO在我的情况下很方便,因为它允许自动确定新架构。有没有办法让这项工作安全?

此外,我想确保在此过程中“FROM(...)”中的源表已锁定。

1 个答案:

答案 0 :(得分:1)

如果您尝试对表进行重大更改(比如在现有列的中间添加列,而不是在最后),使用SSMS并查看它生成的脚本,您将看到SSMS使用{{3 }}

SSMS脚本的一般结构:

  • 使用临时名称
  • 创建一个新表
  • 使用数据填充新表
  • 放下旧桌子
  • 将新表重命名为正确的名称。

交易中的所有这些。

这应该保持表被锁定到最小的时间。

BEGIN TRANSACTION

SELECT (...) INTO dbo.Temp_MyTable FROM (...)

DROP TABLE dbo.MyTable

EXECUTE sp_rename N'dbo.Temp_MyTable', N'dbo.MyTable', 'OBJECT'

COMMIT

DROP TABLE MyTable获取架构修改(Sch-M)锁定,直到事务结束,因此使用MyTable的所有其他查询都会等待。即使其他查询使用READ UNCOMMITTED隔离级别(或臭名昭着的WITH (NOLOCK)提示)。

另请参阅MSDN sp_rename

  

架构锁

     

数据库引擎使用架构修改(Sch-M)   在表数据定义语言(DDL)操作期间锁定,例如   添加列或删除表。在举行期间,   Sch-M锁可防止对表的并发访问。这意味着   Sch-M锁定会阻止所有外部操作,直到锁定被释放。