您的问题本质上是:
为什么我不能再做一开始就不应该做的冒险的事情?
该问题的答案基本上无关紧要(尽管您可以在这些Connect项中看到一些Microsoft注释,要求该功能:#294193和#252226)。为了完整起见,我的提要是:删除标识属性的能力是首先具有破坏系统表的能力的意外副作用。不应以多种方式使用此功能,通常会带来非常严重的后果,因此将其删除。这是一个未经证明,不受支持的系统表黑客。不会删除更改系统表中数据的功能,因为Microsoft不再希望您侵入以身分身份的列之列,而删除该功能是因为处理系统表具有极大的风险。删除IDENTITY属性本身并不是专门针对性的功能删除,即使在有可能的古代,我也永远不会完全信任这种方法。
也就是说,我们如何回答这个问题呢?
如何在停机时间最少或没有停机的情况下删除列的IDENTITY属性?
您可以轻松地使用ALTER TABLE ... SWITCH
这项技术,我肯定是我首先从我们自己的Paul White那里学习的,在Connect#252226的变通办法中。简单的例子,给出这个简单的表:
CREATE TABLE dbo.Original
(
ID INT IDENTITY(1,1) PRIMARY KEY,
name SYSNAME
);
GO
INSERT dbo.Original(name) VALUES(N'foo'),(N'bar');
GO
SELECT * FROM dbo.Original;
GO
结果:
ID name
-- ----
1 foo
2 bar
现在,让我们创建一个影子表,并切换到它,然后删除旧表,重命名新表,然后恢复正常活动:
CREATE TABLE dbo.New
(
ID INT PRIMARY KEY,
name SYSNAME
);
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
ALTER TABLE dbo.Original SWITCH TO dbo.New;
DROP TABLE dbo.Original;
EXEC sys.sp_rename N'dbo.New', N'Original', 'OBJECT';
COMMIT TRANSACTION;
GO
INSERT dbo.Original(ID,name) VALUES(3,N'splunge');
UPDATE dbo.Original SET ID = 6 WHERE ID = 1;
GO
SELECT * FROM dbo.Original;
GO
结果:
ID name
-- -------
2 bar
3 splunge
6 foo
现在清理:
DROP TABLE dbo.Original;
这仅是元数据操作,没有数据移动,并且仅在更新元数据时阻止其他用户。但是,不可否认,这是一个非常简单的例子。如果您有外键或正在使用其他功能(例如复制,更改数据捕获,更改跟踪等),则可能需要在进行此更改之前禁用或删除其中一些功能(我尚未测试所有组合)。特别是对于外键,请参阅此技巧,该技巧显示了如何生成脚本以删除并重新创建所有(或选定的)外键约束。
此外,您将需要更新应用程序代码,以免SQL Server填充此列,并检查可能取决于列顺序或它们需要指定的列的所有insert或select语句。通常,对于此表的任何提及,我都会复制整个代码库。
另请参阅Itzik Ben-Gan的脚本(来源:此古老的文章),以了解另一种处理此问题的方法,但是这里涉及数据移动,因此它不能满足“无停机时间或最少停机时间”的要求。