我需要将一个表的主键更改为一个标识列,并且在表中已经有许多行。
我有一个脚本来清理id,以确保它们从1开始是顺序的,在我的测试数据库上运行良好。
更改列以具有标识属性的SQL命令是什么?
我需要将一个表的主键更改为一个标识列,并且在表中已经有许多行。
我有一个脚本来清理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
已经说过,有一种方法可以通过设置位值来破解系统表,但这是不支持的,我不会这么做
其他回答
您不能更改现有列的标识。
你有两个选择,
创建一个带有标识的新表并删除现有表 创建一个具有标识的新列并删除现有列
方法1。(新表)在这里,您可以保留新创建的标识列上的现有数据值。请注意,如果不满足'if not exists',您将丢失所有数据,因此请确保您将条件也放在drop上!
CREATE TABLE dbo.Tmp_Names
(
Id int NOT NULL
IDENTITY(1, 1),
Name varchar(50) NULL
)
ON [PRIMARY]
go
SET IDENTITY_INSERT dbo.Tmp_Names ON
go
IF EXISTS ( SELECT *
FROM dbo.Names )
INSERT INTO dbo.Tmp_Names ( Id, Name )
SELECT Id,
Name
FROM dbo.Names TABLOCKX
go
SET IDENTITY_INSERT dbo.Tmp_Names OFF
go
DROP TABLE dbo.Names
go
Exec sp_rename 'Tmp_Names', 'Names'
方法2(新列)不能在新创建的标识列上保留现有数据值,标识列将保留数字序列。
Alter Table Names
Add Id_new Int Identity(1, 1)
Go
Alter Table Names Drop Column ID
Go
Exec sp_rename 'Names.Id_new', 'ID', 'Column'
请参阅以下Microsoft SQL Server论坛帖子了解更多细节:
如何将列更改为identity(1,1)
这里有一个很酷的解决方案: 在列上添加或删除标识属性
简而言之,在SQL管理器中手动编辑您的表,切换标识,不要保存更改,只显示将为更改创建的脚本,复制它并稍后使用。
这节省了大量的时间,因为它(脚本)包含了所有与您更改的表相关的外键、索引等。手动写这个…上帝保佑。
如果最初的海报实际上想要设置一个现有的列为表的PRIMARY KEY,实际上不需要列为IDENTITY列(两种不同的东西),那么这可以通过t-SQL完成:
ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])
请注意,在PRIMARY KEY选项之后,列名周围的括号。
虽然这篇文章是旧的,我只是对请求者的需求做了一个假设,但我觉得这些额外的信息可能会对遇到这个线程的用户有所帮助,因为我相信对话可能会导致一个人认为,如果不先将现有的列添加为新列,就不能将其设置为主键,这是不正确的。
遗憾的是,没有一个;IDENTITY属性属于表而不是列。
更简单的方法是在GUI中完成,但如果没有这个选项,则可以复制数据、删除列、用标识重新添加它,然后放回数据。
请看这里的详细说明。
我是一名java开发人员,碰巧加入了一个没有DBA的团队,而作为一名开发人员,我无法获得DBA权限。我的任务是在两个数据库之间移动整个模式,所以没有DBA,我必须通过运行脚本来完成,不能使用SQL Server 2008中的GUI,因为我没有管理权限。
但是,在新模式上运行存储过程时,所有内容都被移动了。表,我发现我丢失了一个表的标识字段。我仔细检查了创建表的脚本,它在那里,但是,SQL Server在我运行脚本时没有得到它。后来,一位DBA告诉我,他以前见过同样的问题。
在任何情况下,对于SQL Server 2008,这些是我采取的步骤来解决这个问题,他们工作,所以我张贴在这里,希望它会对某人有所帮助。这是我所做的,因为我对另一个表有FK依赖,这使得这更困难:
我使用这个查询来验证标识确实缺失,并查看表上的依赖关系。
1)。查找表上的统计信息:
exec sp_help 'dbo.table_name_old';
2)。创建一个重复的、完全相同的新表,只是在原来的PK字段上添加了一个标识字段。
3)。禁用标识以移动数据。
SET IDENTITY_INSERT dbo.table_name ON
4)。传输数据。
INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT
field1, field2, etc...
FROM
dbo.table_name_old;
5)。验证数据是否存在。
SELECT * FROM dbo.table_name_new
6)。重新启用标识。
SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF
7)。这是我找到的获得所有FK关系以验证原始表引用哪个表作为依赖项的最佳脚本 我遇到过很多,所以它是一个保存者!
SELECT f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
ORDER BY ReferenceTableName;
8)。在进行下一步之前,请确保您拥有所有涉及到的表的所有PK和FK脚本。
9)。您可以右键单击每个键并使用SQL Server 2008编写脚本
10)。使用以下语法从依赖表中删除FK:
ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]
11)。删除原来的表:
DROP TABLE dbo.table_name_old;
13)。接下来的步骤依赖于您在SQL Server 2008第9步中创建的脚本。
将PK添加到新表中。
——将FK添加到新表中。
——将FK添加回依赖项表。
14)。验证所有内容是否正确和完整。我使用GUI查看表格。
15)。将新表重命名为原始表名。
exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';
最后,一切都成功了!