1

我已通过事务复制将一系列表从 SQL Server 2008 迁移到新的 SQL Server 2012 机器。到目前为止效果很好,我还复制了索引和默认值,以确保复制的数据与原始数据相同。

当我将新机器从复制中分离出来以独立作为旧机器的替代品时,SQL Server 开始填充我的标识列中的所有空白,这可能会导致不同的问题。即我的代码不能再依赖于最后插入的行的最高 ID。以前删除的用户 ID 也会被回收,这也可能导致用户方面的混乱。

有没有办法让我的数据库的新实例与旧的复制实例完全一样?以我的经验,数据库的运行实例永远不会填补先前删除的行的空白。

4

1 回答 1

1

我也从来没有见过这个。但是,表在部署时可能会重新设置为 0。观察这个例子:

SET NOCOUNT ON;
GO
CREATE TABLE dbo.fooblat(id INT IDENTITY(1,1));
GO
INSERT dbo.fooblat DEFAULT VALUES;
GO 3
DELETE dbo.fooblat WHERE id = 2;
GO
DBCC CHECKIDENT('dbo.fooblat', RESEED, 0);
GO
INSERT dbo.fooblat DEFAULT VALUES;
GO 3
SELECT id FROM dbo.fooblat ORDER BY id;
GO
DROP TABLE dbo.fooblat;

结果:

id
----
1
1
2
3
3

现在,如果标识列也是主键或唯一的,同样的操作仍然可以填补空白,只有重复的违规行为会失败。所以再次重复这个表定义:

CREATE TABLE dbo.fooblat(id INT IDENTITY(1,1) PRIMARY KEY);
GO

产生这个(第一个成功的插入填补了空白):

id
----
1
2
3

消息 2627,级别 14,状态 1,第 1 行
违反主键约束“PK_ fooblat _3213E83F6BF0A0C6”。无法在对象“dbo.fooblat”中插入重复键。重复键值为 (1)。
消息 2627,级别 14,状态 1,第 1 行
违反主键约束“PK_ fooblat _3213E83F6BF0A0C6”。无法在对象“dbo.fooblat”中插入重复键。重复键值为 (3)。

您可以通过确保在将表放在其他系统上时正确播种表来避免这种情况。这可能只是意味着使用更可靠的部署技术,或者可能意味着 - 在填充之后和让任何用户进入之前 - 你做这样的事情:

DECLARE @i INT, @sql NVARCHAR(MAX);
SELECT @i = MAX(id) FROM dbo.fooblat;
SET @sql = N'DBCC CHECKIDENT(''dbo.fooblat'', RESEED, ' + RTRIM(@i) + ');';
EXEC sp_executesql @sql;
于 2013-02-13T02:08:26.187 回答