我需要将一个表的主键更改为一个标识列,并且在表中已经有许多行。

我有一个脚本来清理id,以确保它们从1开始是顺序的,在我的测试数据库上运行良好。

更改列以具有标识属性的SQL命令是什么?


当前回答

您不能这样做,您需要添加另一列,删除原来的列并重命名新列,或者创建一个新表,复制数据并删除旧表,然后将新表重命名为旧表

如果你使用SSMS并在设计器中将标识属性设置为ON,下面就是SQL Server在幕后所做的事情。因此,如果你有一个名为[user]的表,如果你设置UserID和identity,就会发生这样的情况

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

已经说过,有一种方法可以通过设置位值来破解系统表,但这是不支持的,我不会这么做

其他回答

我不相信您可以使用tsql将现有列更改为标识列。但是,您可以通过Enterprise Manager设计视图来完成。

或者,您可以创建一个新行作为标识列,删除旧列,然后重命名新列。

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED

不能将列更改为IDENTITY列。您需要做的是创建一个新列,从一开始就定义为IDENTITY,然后删除旧列,并将新列重命名为旧名称。

ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'

Marc

您不能这样做,您需要添加另一列,删除原来的列并重命名新列,或者创建一个新表,复制数据并删除旧表,然后将新表重命名为旧表

如果你使用SSMS并在设计器中将标识属性设置为ON,下面就是SQL Server在幕后所做的事情。因此,如果你有一个名为[user]的表,如果你设置UserID和identity,就会发生这样的情况

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

已经说过,有一种方法可以通过设置位值来破解系统表,但这是不支持的,我不会这么做

遗憾的是,没有一个;IDENTITY属性属于表而不是列。

更简单的方法是在GUI中完成,但如果没有这个选项,则可以复制数据、删除列、用标识重新添加它,然后放回数据。

请看这里的详细说明。

根据设计,没有简单的方法来打开或关闭现有列的标识特性。要做到这一点,唯一干净的方法是创建一个新列并使其成为标识列,或者创建一个新表并迁移数据。

如果我们使用SQL Server Management Studio去除列“id”上的标识值,则会创建一个新的临时表,数据被移动到临时表中,旧表被删除,新表被重命名。

使用Management Studio进行更改,然后在设计器中右键单击并选择“生成更改脚本”。

你会看到这就是SQL server在后台所做的。