如何以编程方式更改标识列值?

Tom*_*ski 160 t-sql sql-server identity sql-server-2005 sql-server-2005-express

我有一个Test带有列的表的MS SQL 2005数据库ID.ID是一个标识列.

我在这个表中有行,并且所有行都有相应的ID自动增量值.

现在我想更改此表中的每个ID,如下所示:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON
Run Code Online (Sandbox Code Playgroud)

但是当我这样做时,我收到一个错误:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON
Run Code Online (Sandbox Code Playgroud)

我试过这个:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON
Run Code Online (Sandbox Code Playgroud)

但这并没有解决问题.

我需要将标识设置为此列,但我还需要不时更改值.所以我的问题是如何完成这项任务.

A-K*_*A-K 220

你需要

set identity_insert YourTable ON
Run Code Online (Sandbox Code Playgroud)

然后删除您的行并使用不同的标识重新插入它.

完成插入后,不要忘记关闭identity_insert

set identity_insert YourTable OFF
Run Code Online (Sandbox Code Playgroud)

  • 设置此选项仅在插入数据时有效,而在更新时无效.UPDATE语句仍然会失败. (132认同)
  • 要进行更新,您需要删除并重新插入.别无他法. (31认同)
  • @ ashes999这是4步而不是2.我的答案只有一个(创建表,切换,更新,切换回,删除)可能你更熟悉这些步骤,所以它们看起来不那么复杂.更新可以更有效,然后在涉及许多行时删除插入.你还在哪里拿着删除的行?如果你放弃的那个`#temp`表就是另一个你没有在这里计算的步骤. (3认同)

Mar*_*ith 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'
Run Code Online (Sandbox Code Playgroud)

那你可以做

/*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*/
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)


Mic*_*yor 26

通过SQL Server 2005管理器中的UI,更改列删除列的自动编号(标识)属性(通过右键单击选择表并选择"设计").

然后运行您的查询:

UPDATE table SET Id = Id + 1
Run Code Online (Sandbox Code Playgroud)

然后,将autonumber属性添加回列.

  • 如果手动进行更改,则可以要求管理器生成更改的SQL脚本(表设计器菜单,生成更改脚本).对于此更改,它会创建一个新表并复制数据,然后删除原始数据. (3认同)
  • @tomaszs - 一个代码示例,它也更高效,因为它根本没有物理重建表(这会这样做两次)是在我的后期[这里](http://stackoverflow.com/a/17249583/73226 ) (2认同)

Mil*_*s D 18

首先,为此开启或关闭IDENTITY_INSERT的设置将不适用于您需要的内容(它用于插入新值,例如插入间隙).

通过GUI执行操作只会创建一个临时表,将所有数据复制到没有标识字段的新表中,并重命名该表.


Man*_*dra 9

这可以使用临时表来完成.

这个想法

  • 禁用约束(如果您的id被外键引用)
  • 使用新id创建临时表
  • 删除表格内容
  • 将复制的表中的数据复制回原始表
  • 启用预先禁用的约束

SQL查询

比方说,你test的表有两个附加列(column2column3),并有2个表有外键引用test所谓的foreign_table1foreign_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;
Run Code Online (Sandbox Code Playgroud)

而已.


小智 6

DBCC CHECKIDENT('databasename.dbo.orders',RESEED,999)您可以使用此命令更改任何标识列号,并且您也可以从您想要的每个数字开始该字段编号.例如,在我的命令中,我要求从1000(999 + 1)希望它就够了......祝你好运