我有一个MS SQL 2005数据库,其中包含Test
列ID
列。 ID
是一个标识列。
我在这个表中有行,并且所有行都有相应的ID自动递增值。
现在我想更改此表中的每个ID,如下所示:
ID = ID + 1
但是当我这样做时,我收到一个错误:
无法更新标识列“ID”。
我试过这个:
ALTER TABLE Test NOCHECK CONSTRAINT ALL
set identity_insert ID ON
但这并没有解决问题。
我需要将标识设置为此列,但我还需要不时更改值。所以我的问题是如何完成这项任务。
答案 0 :(得分:217)
你需要
set identity_insert YourTable ON
然后删除您的行并以不同的身份重新插入。
完成插入操作后,请不要忘记关闭identity_insert
set identity_insert YourTable OFF
答案 1 :(得分:40)
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
答案 2 :(得分:26)
通过SQL Server 2005管理器中的UI,更改列删除列的autonumber(identity)属性(通过右键单击选择表并选择“Design”)。
然后运行您的查询:
UPDATE table SET Id = Id + 1
然后将自动编号属性添加回列。
答案 3 :(得分:18)
首先,对此事项开启或关闭IDENTITY_INSERT的设置将不适用于您所需的内容(它用于插入新值,例如插入间隙)。
通过GUI执行操作只会创建一个临时表,将所有数据复制到没有标识字段的新表中,并重命名该表。
答案 4 :(得分:9)
这可以使用临时表来完成。
假设您的test
表有两个额外的列(column2
和column3
),并且有2个表的外键引用test
,称为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;
就是这样。
答案 5 :(得分:6)
DBCC CHECKIDENT('databasename.dbo.orders',RESEED,999) 您可以使用此命令更改任何标识列号,也可以从您想要的每个数字开始该字段编号。例如,在我的命令中,我要求从1000开始(999 + 1) 希望这就够了......祝你好运
答案 6 :(得分:4)
如果该列不是PK,您可以随时在表格中使用递增的数字创建一个新列,删除原始列,然后将新的列更改为旧的。
好奇为什么你可能需要这样做...大多数我曾经不得不使用Identity专栏来回填数字,我最后使用了DBCC CHECKIDENT(tablename,RESEED,newnextnumber)
祝你好运!答案 7 :(得分:1)
身份修改可能会失败,具体取决于许多因素,主要是围绕链接到id列的对象/关系。似乎数据库设计在这里是问题,因为id应该很少,如果有变化(我确定你有你的理由,并且正在改变)。如果你真的需要不时更改id,我建议你创建一个新的虚拟id列,它不是你可以自己管理并从当前值生成的主键/自动编号。或者,如果您在允许身份插入时遇到问题,那么上面的Chrisotphers想法将是我的另一个建议。
祝你好运PS它没有失败,因为它运行的顺序正在尝试将列表中的值更新为已存在于ID列表中的项目?抓住吸管,或许添加行数+ 1,然后如果可行则减去行数:-S
答案 8 :(得分:1)
如果您需要偶尔更改ID,最好不要使用标识列。过去,我们使用“计数器”表手动实现自动编号字段,该表跟踪每个表的下一个ID。 IIRC我们这样做是因为标识列导致SQL2000中的数据库损坏,但能够更改ID有时对测试很有用。
答案 9 :(得分:1)
您可以插入具有修改值的新行,然后删除旧行。以下示例更改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
答案 10 :(得分:1)
首先保存所有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
设置为关闭,则会收到以下错误:
无法在表'Test'中为identity列插入显式值 IDENTITY_INSERT设置为OFF。
答案 11 :(得分:0)
我看到一篇很好的文章在最后一刻帮助了我..我试图在一个有标识列的表中插入几行但是做错了而且必须删除。删除行后,我的标识列发生了变化。我试图找到一种方法来更新插入的列但是 - 没有运气。所以,在google上搜索时发现了一个链接..
答案 12 :(得分:0)
非常好的问题,首先我们需要 on 特定表的IDENTITY_INSERT,之后运行插入查询(必须指定列名)。
注意:修改标识列后,请不要忘记关闭 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