Kir*_*ein 421 sql sql-server alter-table identity-column
我需要将表的主键更改为标识列,并且表中已有许多行.
我有一个脚本来清理ID以确保它们从1开始顺序启动,在我的测试数据库上运行正常.
什么是将命令改为具有标识属性的SQL命令?
Joh*_*som 456
您无法更改现有列的标识.
你有2个选择,
使用标识创建一个新表并删除现有表
使用标识创建新列并删除现有列
方法1.(新表)您可以在此处保留新创建的标识列上的现有数据值.
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'
Run Code Online (Sandbox Code Playgroud)
方法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'
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅以下Microsoft SQL Server论坛帖子:
Jus*_*ant 200
在SQL 2005及更高版本中,可以在不更改表的数据页的情况下解决此问题.这对于触摸每个数据页可能需要几分钟或几小时的大型表非常重要.特技也适用即使标识列是主键,是一个聚集或非聚集索引,或可绊倒的简单的"添加/删除/重命名列"溶液中的其它陷阱的一部分.
下面是技巧:您可以使用SQL Server的ALTER TABLE ... SWITCH语句来更改表的模式而不更改数据,这意味着您可以使用具有相同表模式但没有IDENTITY列的IDENTITY替换表.同样的技巧可以将IDENTITY添加到现有列.
通常,ALTER TABLE ... SWITCH用于有效地用新的空分区替换分区表中的完整分区.但它也可以用在非分区表中.
我用这个技巧在5秒内将IDENTITY中25亿行表中的一列转换为非IDENTITY(为了运行一个多小时查询,其查询计划更适合非IDENTITY列),然后在不到5秒的时间内恢复IDENTITY设置.
这是一个如何工作的代码示例.
CREATE TABLE Test
(
id int identity(1,1),
somecolumn varchar(10)
);
INSERT INTO Test VALUES ('Hello');
INSERT INTO Test VALUES ('World');
-- copy the table. use same schema, but no identity
CREATE TABLE Test2
(
id int NOT NULL,
somecolumn varchar(10)
);
ALTER TABLE Test SWITCH TO Test2;
-- drop the original (now empty) table
DROP TABLE Test;
-- rename new table to old table's name
EXEC sp_rename 'Test2','Test';
-- update the identity seed
DBCC CHECKIDENT('Test');
-- see same records
SELECT * FROM Test;
Run Code Online (Sandbox Code Playgroud)
这显然比其他答案中的解决方案更复杂,但如果你的桌子很大,这可以真正节省生命.有一些警告:
更新 - Eric Wu在下面发表评论,增加了有关此解决方案的重要信息.在此处复制以确保它得到更多关注:
这里还有另一个值得一提的警告.虽然新表将很乐意从旧表中接收数据,并且所有新行将按照标识模式插入,但它们将从1开始并且如果所述列是主键则可能会中断.考虑
DBCC CHECKIDENT('<newTableName>')
切换后立即运行.有关详细信息,请参阅msdn.microsoft.com/en-us/library/ms176057.aspx.
如果表正在积极与新行扩展(这意味着你没有太多的如果添加的身份和添加新行,然后代替之间的任何停机时间DBCC CHECKIDENT
,你会想手动设置新表模式的身份种子值是大于表中最大的现有ID,例如IDENTITY (2435457, 1)
,您可能能够在事务中包含ALTER TABLE...SWITCH
和DBCC CHECKIDENT
(或者没有 - 没有测试过),但似乎手动设置种子值将更容易和更安全.
显然,如果没有新的行添加到表中(或者它们只是偶尔添加,就像每日ETL过程一样),那么这种竞争条件不会发生,所以DBCC CHECKIDENT
很好.
mar*_*c_s 66
您不能将列更改为IDENTITY列.您需要做的是创建一个新列,该列从一开始就定义为IDENTITY,然后删除旧列,并将新列重命名为旧名称.
ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)
ALTER TABLE (yourTable) DROP COLUMN OldColumnName
EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'
Run Code Online (Sandbox Code Playgroud)
渣
gre*_*man 14
这里描述了很酷的解决方案: SQL SERVER - 在列上添加或删除标识属性
简而言之,在SQL Manager中手动编辑表,切换标识,不保存更改,只显示将为更改创建的脚本,复制并稍后使用.
它节省了大量时间,因为它(脚本)包含与您更改的表相关的所有外键,索引等.手动写这个......上帝保佑.
考虑使用SEQUENCE代替IDENTITY。
在sql server 2014中(我不知道较低的版本),您可以使用序列简单地做到这一点。
CREATE SEQUENCE sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;
ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name
Run Code Online (Sandbox Code Playgroud)
从这里开始:序列作为列的默认值
简单的解释
使用sp_RENAME重命名现有列
EXEC sp_RENAME'Table_Name.Existing_ColumnName','New_ColumnName','COLUMN'
重命名示例:
现有列UserID重命名为OldUserID
EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'
Run Code Online (Sandbox Code Playgroud)
然后使用alter query添加新列以设置为主键和标识值
ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)
Run Code Online (Sandbox Code Playgroud)
设置主键的示例
新创建的列名称是UserID
ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)
Run Code Online (Sandbox Code Playgroud)
然后删除重命名列
ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName
Run Code Online (Sandbox Code Playgroud)
Drop重命名列的示例
ALTER TABLE Users DROP COLUMN OldUserID
Run Code Online (Sandbox Code Playgroud)
现在我们将主键和标识添加到表中的现有列.
我是一名Java开发人员,碰巧加入了一个没有DBA的团队,而作为开发人员,我却无法获得DBA权利。我的任务是在两个数据库之间移动整个架构,因此,没有DBA,我必须通过运行脚本来做到这一点,并且不能在SQL Server 2008中使用GUI,因为我没有管理员权限。
一切都顺利进行,但是,在新的schema.table上运行存储过程时,我发现我丢失了表中的identity字段。我仔细检查了创建表的脚本,它在那里,但是,当我运行脚本时,SQL Server没有得到它。后来,DBA告诉我他以前也遇到过同样的问题。
无论如何,对于SQL Server 2008,这些都是我为解决此问题而采取的步骤,并且它们起作用了,因此,我将其发布在此处,希望对您有所帮助。这是我做的,因为我对另一个表具有FK依赖关系,这使此操作变得更加困难:
我使用此查询来验证身份确实丢失,并查看对表的依赖关系。
1.)在表格上查找统计信息:
exec sp_help 'dbo.table_name_old';
Run Code Online (Sandbox Code Playgroud)
2.)创建一个重复的,相同的新表,不同之处在于,在以前的PK字段上添加一个身份字段。
3.)禁用身份以移动数据。
SET IDENTITY_INSERT dbo.table_name ON
Run Code Online (Sandbox Code Playgroud)
4.)传输数据。
INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT
field1, field2, etc...
FROM
dbo.table_name_old;
Run Code Online (Sandbox Code Playgroud)
5.)确认数据在那里。
SELECT * FROM dbo.table_name_new
Run Code Online (Sandbox Code Playgroud)
6.)重新启用身份。
SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
8.)在下一步之前,请确保您具有所有涉及的表的所有PK和FK脚本。
9.)您可以右键单击每个键,然后使用SQL Server 2008对此脚本编写脚本
10.)使用以下语法从依赖关系表中删除FK:
ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]
Run Code Online (Sandbox Code Playgroud)
11.)删除原始表:
DROP TABLE dbo.table_name_old;
Run Code Online (Sandbox Code Playgroud)
13.)接下来的步骤取决于您在步骤9中在SQL Server 2008中创建的脚本。
-将PK添加到新表。
-将FK添加到新表中。
-将FK添加回依赖表。
14.)验证一切正确和完整。我使用GUI查看表。
15.)将新表重命名为原始表名。
exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';
Run Code Online (Sandbox Code Playgroud)
最后,一切正常!
据我了解,在正常情况下,我们正在创建一个带有具有Identity 属性的主键的表
,因此重命名或删除与主键约束关联的列将是不可能的,因为约束规则正在验证列结构。
要实现此目的,我们必须按以下方式处理一些步骤:
假设TableName = 'Employee'且ColumnName = 'EmployeeId'
1. 在 'Employee' 表中添加新列 'EmployeeId_new'
ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY( 1,1)
现在从“Employee”表中删除“EmployeeId”列
ALTER TABLE Employee DROP COLUMN EmployeeId
这将引发错误,因为主键约束规则适用并验证列结构。
*### '消息 5074,级别 16,状态 1,第 1 行 对象 [PK_dbo.Employee] 依赖于列 [EmployeeId]。' ###
因此,我们必须首先从表“Employee”中删除主键约束,然后才能删除列
ALTER TABLE Employee DROP 约束 [PK_dbo.Employee]
现在我们可以从“Employee”表中删除“EmployeeId”列,就像上一步中出现错误
ALTER TABLE Employee DROP COLUMN EmployeeId一样
现在列“EmployeeId”已从表中删除因此我们将用“EmployeeId”重命名新添加的新列“EmployeeId_new”
sp_rename“Employee.EmployeeId”、“EmployeeId_new”、“COLUMN”
要以与以前相同的形式重新排列表,我们必须为“EmployeeId”列添加主键约束
ALTER TABLE Employee 添加约束 [PK_dbo.Employee] 主键 (EmployeeId)
8.现在,带有“EmployeeId”的表“Employee”已根据身份规则以及现有主键约束进行修改
归档时间: |
|
查看次数: |
822371 次 |
最近记录: |