152

我有一個MS SQL 2005數據庫與表TestIDID是一個標識列。如何以編程方式更改標識列值?

我在這個表中有行,他們都有自己對應的ID自動增量值。

現在我想改變每個ID在該表是這樣的:

ID = ID + 1 

但是當我這樣做,我得到一個錯誤:

Cannot update identity column 'ID'. 

我已經試過這樣:

ALTER TABLE Test NOCHECK CONSTRAINT ALL 
set identity_insert ID ON 

但是這並不能解決問題。

我需要爲此列設置標識,但我需要隨時更改值。所以我的問題是如何完成這項任務。

回答

212

您需要

set identity_insert YourTable ON 

然後刪除行,並與不同的身份重新插入。

一旦你完成插入,不要忘記把IDENTITY_INSERT關閉

set identity_insert YourTable OFF 
26

通過SQL Server 2005管理器中的UI,更改列刪除列的自動編號(標識)屬性(通過右鍵單擊並選擇「設計」)來選擇表。

然後運行查詢:

UPDATE table SET Id = Id + 1 

然後去添加自動編號屬性回到塔。

+4

以及如何從代碼做到這一點? – 2009-04-15 12:52:24

+3

如果您手動進行更改,則可以要求管理器爲更改生成SQL腳本(表設計器菜單,生成更改腳本)。對於此更改,它將創建一個新表並將數據複製,然後刪除原始數據。 – 2009-07-27 09:57:39

+2

@tomaszs - 一個代碼示例也更有效,因爲它根本不重建物理表(這樣做會這樣做兩次)在我遲來的答案[here](http://stackoverflow.com/a/17249583/ 73226) – 2013-06-22 10:19:00

4

如果該列不是PK,則可以隨表格中的增加的數字一起創建一個新列,然後刪除原始數據,然後將其更改爲舊數據。

好奇,爲什麼你可能需要這樣做......最讓我曾經有過與身份列futz是回填數字,我只是結束了使用DBCC CHECKIDENT(表名,RESEED,newnextnumber)

祝你好運!

1

身份修改可能會失敗,具體取決於許多因素,主要圍繞鏈接到id列的對象/關係。看起來像db設計是問題在這裏作爲id應該很少,如果有變化(我相信你有你的理由,並cascasding的變化)。如果您確實需要不時更改ID,我會建議您創建一個新的虛擬ID列,它不是您可以管理自己並使用當前值生成的主鍵/自動編號。或者,如果您在允許身份插入方面遇到問題,Chrisotphers的想法也是我的另一個建議。

好運

PS這不是失敗,因爲它的運行的順序試圖更新列表中的一個已經存在的ID列表的項目的價值?抓住吸管,也許增加行數+ 1,那麼如果這樣工作減去行數:-S

18

首先,開啓或關閉IDENTITY_INSERT設置對於這個問題將無法滿足您的要求(它是用於插入新值,如堵塞間隙)。

通過GUI執行操作只是創建一個臨時表,將所有數據複製到沒有標識字段的新表中,然後重命名該表。

1

如果您偶爾需要更改ID,最好不要使用標識列。在過去,我們使用'Counters'表來手動實現自動編號字段,該表跟蹤每個表的下一個ID。 IIRC我們這樣做是因爲標識列在SQL2000中導致數據庫損壞,但能夠更改ID偶爾對測試有用。

6

DBCC CHECKIDENT( 'databasename.dbo.orders',RESEED,999) 你可以改變任何與此標識列數命令,也可以從你想要的每個數字開始這個字段號。例如在我的命令中,我要求從1000(999 + 1) 開始,希望它足夠了...祝你好運

9

這可以可以使用臨時表來完成。

想法

  • 禁用約束(如果您的ID是由外鍵引用)
  • 創建臨時表與新的ID
  • 刪除表的內容
  • 複製回數據從複製表格到原始表格
  • 啓用預先禁用的約束條件

SQL查詢

比方說,你test表有兩個附加列(column2column3),並有有外鍵引用test稱爲foreign_table1foreign_table2(因爲現實生活中的問題從來都不簡單)2個表。

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; 

就是這樣。

0

我看到一篇很好的文章,幫助我在最後一刻......我試圖插入幾行的表中有一列標識列,但做錯了,不得不刪除回來。一旦我刪除了行,我的標識列就被更改了。我試圖找到一種方法來更新插入的列,但沒有運氣。因此,儘管搜索對谷歌找到了一個鏈接..

  1. 刪除其被錯誤插入使用身份
  2. 使用武力插入開/關(下文解釋)列

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-update-the-value-of-an.aspx

39

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 
1

你可以用mod插入新行ified值,然後刪除舊的行。下面的例子改變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 
0

非常好的問題,首先我們需要將IDENTITY爲特定的表,之後運行插入查詢(必須指定列名)。

注:編輯後的標識列,不要忘了關 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

1

首先保存所有ID和編程改變他們你wan't的值,然後從數據庫中刪除它們,然後再次使用類似的東西將它們插入:

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爲關閉您將收到以下錯誤:

Cannot insert explicit value for identity column in table 'Test' when IDENTITY_INSERT is set to OFF.

相關問題