我正在尝试创建一个存储过程,从头开始重新创建一个表,可能会更改架构(包括列的可能添加/删除),方法是使用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(...)”中的源表不已锁定。
答案 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锁定会阻止所有外部操作,直到锁定被释放。