如何以编程方式更改标识列值?
我有一个MS SQL 2005数据库与列ID
Test
表。 ID
是一个标识列。
我在这个表中有行,所有的都有自己对应的ID自动增量值。
现在我想改变这个表中的每个ID,像这样:
ID = ID + 1
但是当我这样做,我得到一个错误:
Cannot update identity column 'ID'.
我试过这个:
ALTER TABLE Test NOCHECK CONSTRAINT ALL set identity_insert ID ON
但是这并不能解决问题。
我需要为此列设置标识,但是我需要不时更改值。 所以我的问题是如何完成这个任务。
你需要
set identity_insert YourTable ON
然后删除你的行,重新插入不同的身份。
一旦你完成插入不要忘记closuresidentity_insert
set identity_insert YourTable OFF
IDENTITY
列值是不可变的。
但是,可以切换表元数据以删除IDENTITY
属性,执行更新,然后切换回来。
假设以下结构
CREATE TABLE Test ( ID INT IDENTITY(1,1) PRIMARY KEY, X VARCHAR(10) ) INSERT INTO Test OUTPUT INSERTED.* SELECT 'Foo' UNION ALL SELECT 'Bar' UNION ALL SELECT 'Baz'
那你可以做
/*Define table with same structure but no IDENTITY*/ CREATE TABLE Temp ( ID INT PRIMARY KEY, X VARCHAR(10) ) /*Switch table metadata to new structure*/ ALTER TABLE Test SWITCH TO Temp; /*Do the update*/ UPDATE Temp SET ID = ID + 1; /*Switch table metadata back*/ ALTER TABLE Temp SWITCH TO Test; /*ID values have been updated*/ SELECT * FROM Test /*Safety check in case error in preceding step*/ IF NOT EXISTS(SELECT * FROM Temp) DROP TABLE Temp /*Drop obsolete table*/
在SQL Server 2012中,可以有一个自动递增列,也可以使用SEQUENCES
更直接地进行更新
CREATE SEQUENCE Seq AS INT START WITH 1 INCREMENT BY 1 CREATE TABLE Test2 ( ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY, X VARCHAR(10) ) INSERT INTO Test2(X) SELECT 'Foo' UNION ALL SELECT 'Bar' UNION ALL SELECT 'Baz' UPDATE Test2 SET ID+=1
通过SQL Server 2005pipe理器中的用户界面,更改列删除列的自动编号(标识)属性(右键单击并select“devise”)select表。
然后运行您的查询:
UPDATE table SET Id = Id + 1
然后去添加自动编号属性回到列。
首先,开启或closuresIDENTITY_INSERT的设置不会满足您的要求(用于插入新值,如插入间隙)。
通过GUI执行操作只是创build一个临时表,将所有数据复制到一个没有标识字段的新表中,然后重命名该表。
这可以使用临时表来完成。
这个想法
- 禁用约束(万一您的ID由外键引用)
- 用新的ID创build一个临时表
- 删除表格内容
- 将数据从复制的表格复制到原始表格
- 启用预先禁用的约束
SQL查询
假设您的test
表有两个额外的列( column2
和column3
),并且有两个引用foreign_table1
和foreign_table2
(因为现实生活中的问题从来不简单)的引用外键的表。
alter table test nocheck constraint all; alter table foreign_table1 nocheck constraint all; alter table foreign_table2 nocheck constraint all; set identity_insert test on; select id + 1 as id, column2, column3 into test_copy from test v; delete from test; insert into test(id, column2, column3) select id, column2, column3 from test_copy alter table test check constraint all; alter table foreign_table1 check constraint all; alter table foreign_table2 check constraint all; set identity_insert test off; drop table test_copy;
而已。
DBCC CHECKIDENT('databasename.dbo.orders',RESEED,999)你可以用这个命令改变任何标识列号,也可以从你想要的每个数字开始这个字段号。例如在我要求从我的命令开始1000(999 + 1)希望这足够了…祝你好运
如果列不是PK,则可以在表格中用增加的数字总是创build一个新列,然后删除原始列,然后将新列更改为旧列。
好奇为什么你可能需要做到这一点…我曾经不得不与身份列futz回填数字,我刚刚结束了使用DBCC CHECKIDENT(表名,RESEED,newnextnumber)
祝你好运!
身份修改可能会失败,取决于许多因素,主要围绕链接到ID列的对象/关系。 看起来像dbdevise是问题在这里作为id应该很less,如果有变化(我敢肯定,你有你的理由,cascasding的变化)。 如果你真的需要不时更改ID,我会build议创build一个新的哑ID列,而不是主键/自动编号,你可以pipe理自己,并从当前值生成。 或者,上面的Chrisotphers的想法是我的另一个build议,如果你有问题,允许身份插入。
祝你好运
PS它没有失败,因为它正在运行的连续顺序是试图更新列表中的值到一个已经存在于ID列表中的项目? 抓着吸pipe,也许加上行数+ 1,那么如果这样做减去行数:-S
如果偶尔需要更改ID,最好不要使用标识列。 在过去,我们使用“Counters”表来手动实现自动编号字段,该表跟踪每个表的下一个ID。 IIRC我们这样做是因为标识列在SQL2000中导致数据库损坏,但是能够更改ID偶尔对testing有用。
您可以插入具有修改值的新行,然后删除旧行。 下面的示例更改ID与外键PersonId相同
SET IDENTITY_INSERT [PersonApiLogin] ON INSERT INTO [PersonApiLogin]( [Id] ,[PersonId] ,[ApiId] ,[Hash] ,[Password] ,[SoftwareKey] ,[LoggedIn] ,[LastAccess]) SELECT [PersonId] ,[PersonId] ,[ApiId] ,[Hash] ,[Password] ,[SoftwareKey] ,[LoggedIn] ,[LastAccess] FROM [db304].[dbo].[PersonApiLogin] GO DELETE FROM [PersonApiLogin] WHERE [PersonId] <> ID GO SET IDENTITY_INSERT [PersonApiLogin] OFF GO
首先保存所有的ID,并以编程方式将它们改为你想要的值,然后从数据库中删除它们,然后再用类似的方法插入它们:
use [Name.Database] go set identity_insert [Test] ON insert into [dbo].[Test] ([Id]) VALUES (2) set identity_insert [Test] OFF
对于批量插入使用:
use [Name.Database] go set identity_insert [Test] ON BULK INSERT [Test] FROM 'C:\Users\Oscar\file.csv' WITH (FIELDTERMINATOR = ';', ROWTERMINATOR = '\n', KEEPIDENTITY) set identity_insert [Test] OFF
来自file.csv的示例数据:
2; 3; 4; 5; 6;
如果你没有设置identity_insert
closures,你会得到以下错误:
当IDENTITY_INSERT设置为OFF时,不能在表“Test”中为标识列插入显式值。
我看到一篇很好的文章,帮助我在最后一刻..我试图插入几行有一个标识列,但做错了,不得不删除回来。 一旦我删除行,然后我的身份列被改变。 我试图find一种方法来更新插入的列,但没有运气。 所以,当在谷歌searchfind一个链接..
- 删除了错误插入的列
- 使用强制插入使用身份开/关(下面解释)
http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column-how-do- I-更新的值-的-an.aspx
非常好的问题,首先我们需要在 IDENTITY_INSERT为特定表,之后运行插入查询(必须指定列名称)。
注意:编辑标识列后,不要忘记closures IDENTITY_INSERT。 如果没有完成,则无法编辑任何其他表的标识列。
SET IDENTITY_INSERT Emp_tb_gb_Menu ON INSERT Emp_tb_gb_Menu(MenuID) VALUES (68) SET IDENTITY_INSERT Emp_tb_gb_Menu OFF
http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html