为什么不支持删除列上的 Identity 属性

Vac*_*ano 12 sql-server identity

我读过,在 SQL Server 2000 之后,删除了“取消标识”标识列的能力。而且这是“按设计”(不仅仅是缺失的功能)。

这是我在博客上找到的一个例子。它涉及更新系统表。(并且在 SQL Server 2000 之后删除了该功能。)我认为通过系统表执行此操作不是一个好主意。我只是想知道为什么没有以另一种方式执行此操作的功能。

解决这个问题会给我带来大量的工作。(在不容忍停机的环境中将数亿行复制到新表中。)

所以我想我会问“为什么”。

Sql Server 2005 和更高版本中的哪些更改使这成为一件坏事?或者它总是很糟糕,只是没有被锁定?

再次将标识列设为普通列会违反什么“最佳实践”(或类似原则)?

——

更新以回答“我为什么这样做”的请求:
这是一个非常高级的摘要:我将开始向我的表添加分区。(这样我就可以存档/清除旧数据。)这很容易。但我偶尔需要将记录移动到不同的分区,这样它就不会被删除(当一个分区出现进行归档/删除时)。(我的分区列增加了 2,以便始终有空间将行移动到不同的分区。)

但是如果分区列是标识列,那么我必须删除并重新插入值(没有办法更新标识列的值)。这会导致复制问题。

所以我想使用序列而不是标识列。但是这种切换在大型数据库上非常困难。

Aar*_*and 22

你的问题基本上是:

为什么我不能再做这种我一开始就不应该被允许做的冒险事情?

该问题的答案在很大程度上无关紧要(尽管您可以在这些 Connect 项目中看到一些 Microsoft 评论要求此功能:#294193#252226)。

为完整起见,我的概要是: 删除身份属性的能力首先是能够弄乱系统表的意外副作用。这并不打算以多种方式使用,通常会产生非常糟糕的后果,因此它被删除了。

这是一个未记录的、不受支持的系统表黑客攻击。更改系统表中数据的能力没有被删除,因为 Microsoft 不再希望你破解作为标识列的列,它被删除是因为与系统表混杂是非常危险的。删除IDENTITY属性本身并不是专门针对功能删除的,即使在可能的古代,我也永远不会完全相信这种方法。

也就是说,我们来回答这个问题怎么样?

如何在最少或没有停机时间的情况下删除列的 IDENTITY 属性?

您可以使用 轻松地做到这一点,ALTER TABLE ... SWITCH我确信这是我在Connect #252226的解决方法中首先从我们自己的Paul White那里学到的技术。给出这个简单的表的快速示例:

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
Run Code Online (Sandbox Code Playgroud)

结果:

ID 姓名
1
2 酒吧

现在,让我们创建一个影子表,并切换到它,然后删除旧表,重命名新表,然后恢复正常活动:

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
Run Code Online (Sandbox Code Playgroud)

结果:

ID 姓名
2 酒吧
3 挥霍
6

现在清理:

DROP TABLE dbo.Original;
Run Code Online (Sandbox Code Playgroud)

这只是一个元数据操作,没有数据移动,并且只会在元数据更新时阻止其他用户。但是,不可否认,这是一个非常简单的例子。如果您有外键或正在使用其他功能,如复制、变更数据捕获、变更跟踪等,您可能需要在进行此更改之前禁用或删除其中的一些功能(我尚未测试所有组合)。对于外键,请参阅此提示,其中显示了如何生成脚本以删除和重新创建所有(或选定的)外键约束。

此外,您将需要更新您的应用程序代码,不要期望 SQL Server 填充此列,并检查可能取决于列顺序或它们需要指定的列的任何插入或选择语句。通常,我会 grep 您的整个代码库以查找任何提及此表的内容。

另请参阅Itzik Ben-Gan 的此脚本(来源:这篇古老的文章),了解另一种处理此问题的方法,但此处涉及数据移动,因此它无法满足“无停机时间或最少停机时间”的要求。