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

发布于 2024-07-17 06:54:30 字数 472 浏览 8 评论 0原文

我有一个 MS SQL 2005 数据库,其中有一个带有 ID 列的 Test 表。 ID 是一个身份列。

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

现在我想像这样更改此表中的每个 ID:

ID = ID + 1

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

无法更新身份列“ID”。

我已经尝试过:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

但这并不能解决问题。

我需要为此列设置身份,但我也需要不时更改值。 所以我的问题是如何完成这个任务。

I have a MS SQL 2005 database with a table Test with column ID. ID is an identity column.

I have rows in this table and all of them have their corresponding ID auto incremented value.

Now I would like to change every ID in this table like this:

ID = ID + 1

But when I do this I get an error:

Cannot update identity column 'ID'.

I've tried this:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

But this does not solve the problem.

I need to have identity set to this column, but I need to change values as well from time to time. So my question is how to accomplish this task.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

你丑哭了我 2024-07-24 06:54:30

您需要

set identity_insert YourTable ON

然后删除您的行并使用不同的身份重新插入它。

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

set identity_insert YourTable OFF

You need to

set identity_insert YourTable ON

Then delete your row and reinsert it with different identity.

Once you have done the insert don't forget to turn identity_insert off

set identity_insert YourTable OFF
疏忽 2024-07-24 06:54:30

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

IDENTITY column values are immutable.

However it is possible to switch the table metadata to remove the IDENTITY property, do the update, then switch back.

Assuming the following structure

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'

Then you can do

/*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*/

In SQL Server 2012 it is possible to have an auto incrementing column that can also be updated more straightforwardly with 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
梦在深巷 2024-07-24 06:54:30

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

然后运行您的查询:

UPDATE table SET Id = Id + 1

然后将自动编号属性添加回该列。

Through the UI in SQL Server 2005 manager, change the column remove the autonumber (identity) property of the column (select the table by right clicking on it and choose "Design").

Then run your query:

UPDATE table SET Id = Id + 1

Then go and add the autonumber property back to the column.

残月升风 2024-07-24 06:54:30

首先,IDENTITY_INSERT 的打开或关闭设置将无法满足您的要求(它用于插入新值,例如堵塞间隙)。

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

Firstly the setting of IDENTITY_INSERT on or off for that matter will not work for what you require (it is used for inserting new values, such as plugging gaps).

Doing the operation through the GUI just creates a temporary table, copies all the data across to a new table without an identity field, and renames the table.

情话墙 2024-07-24 06:54:30

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

这个想法

  • 禁用约束(如果你的id被外键引用)
  • 创建一个带有新id的临时表
  • 删除表内容
  • 将数据从复制的表复制回原始表
  • 启用先前禁用的约束

SQL查询

假设你的test 表有两个附加列(column2column3),并且有 2 个表具有引用 test 的外键,称为 < code>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;

就是这样。

This can be done using a temporary table.

The idea

  • disable constraints (in case your id is referenced by a foreign key)
  • create a temp table with the new id
  • delete the table content
  • copy back data from the copied table to your original table
  • enable previsously disabled constraints

SQL Queries

Let's say your test table have two additional columns (column2 and column3) and that there are 2 tables having foreign keys referencing test called foreign_table1 and foreign_table2 (because real life issues are never simple).

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;

That's it.

智商已欠费 2024-07-24 06:54:30

DBCC CHECKIDENT ('数据库名称.dbo.订单',RESEED, 999)
您可以使用此命令更改任何标识列编号,也可以从您想要的每个数字开始该字段编号。例如,在我的命令中,我要求从 1000 (999+1) 开始
希望这足够了...祝你好运

DBCC CHECKIDENT ( ‘databasename.dbo.orders’,RESEED, 999)
you can change any identity column number with this command,and also you can start that field number from every number you want.for example in my command i ask to start from 1000 (999+1)
hope that it would be enough...good luck

东北女汉子 2024-07-24 06:54:30

如果该列不是 PK,您始终可以在表中使用递增的数字创建一个新列,删除原始列,然后将新列更改为旧列。

很好奇为什么你可能需要这样做......我对 Identity 列进行的大多数操作都是回填数字,我最终使用了 DBCC CHECKIDENT (表名,RESEED,newnextnumber)

祝你好运!

If the column is not a PK you could always create a NEW column in the table with the incremented numbers, drop the original and then alter the new one to be the old.

curious as to why you might need to do this... most I've ever had to futz with Identity columns was to backfill numbers and I just ended up using DBCC CHECKIDENT ( tablename,RESEED,newnextnumber)

good luck!

青瓷清茶倾城歌 2024-07-24 06:54:30

身份修改可能会失败,具体取决于多种因素,主要围绕链接到 id 列的对象/关系。 看来数据库设计是这里的问题,因为 id 应该很少改变(我确信你有你的理由并且正在级联更改)。 如果您确实需要不时更改 id,我建议您创建一个新的虚拟 id 列,该列不是您可以自行管理并从当前值生成的主键/自动编号。 或者,如果您在允许身份插入方面遇到问题,上面的 Chrisotphers 想法将是我的另一个建议。

祝你好运

PS 它没有失败,因为它运行的顺序是尝试将列表中的值更新为 ids 列表中已存在的项目? 抓住救命稻草,也许添加行数+1,然后如果可行的话减去行数:-S

Identity modifying may fail depending on a number of factors, mainly revolving around the objects/relationships linked to the id column. It seems like db design is as issue here as id's should rarely if ever change (i'm sure you have your reasons and are cascasding the changes). If you really need to change id's from time to time, I'd suggest either creating a new dummy id column that isn't the primary key/autonumber that you can manage yourself and generate from the current values. Alternately, Chrisotphers idea above would be my other suggestion if you're having issues with allowing identity insert.

Good luck

PS it's not failing because the sequential order it's running in is trying to update a value in the list to an item that already exists in the list of ids? clutching at straws, perhaps add the number of rows+1, then if that works subtract the number of rows :-S

世界和平 2024-07-24 06:54:30

如果您偶尔需要更改 ID,最好不要使用标识列。 过去,我们使用“计数器”表手动实现自动编号字段,该表跟踪每个表的下一个 ID。 IIRC 我们这样做是因为身份列会导致 SQL2000 中的数据库损坏,但能够更改 ID 偶尔对测试很有用。

If you need to change the IDs occasionally, it's probably best not to use an identity column. In the past we've implemented autonumber fields manually using a 'Counters' table that tracks the next ID for each table. IIRC we did this because identity columns were causing database corruption in SQL2000 but being able to change IDs was occasionally useful for testing.

靖瑶 2024-07-24 06:54:30

您可以插入具有修改值的新行,然后删除旧行。 以下示例将 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

You can insert new rows with modified values and then delete old rows. Following example change ID to be same as foreign key 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
遇到 2024-07-24 06:54:30

首先保存所有 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 关闭,您将收到以下错误:

无法在表“测试”中插入标识列的显式值
IDENTITY_INSERT 设置为 OFF。

First save all IDs and alter them programmatically to the values you wan't, then remove them from database and then insert them again using something similar:

use [Name.Database]
go
set identity_insert [Test] ON
insert into [dbo].[Test]
           ([Id])
     VALUES
           (2)
set identity_insert [Test] OFF

For bulk insert use:

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

Sample data from file.csv:

2;
3;
4;
5;
6;

If you don't set identity_insert to off you will get the following error:

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

ま昔日黯然 2024-07-24 06:54:30

我看到一篇好文章在最后一刻帮助了我。我试图在具有标识列的表中插入几行,但做错了,必须删除回来。 一旦我删除了行,我的身份列就会发生变化。 我试图找到一种方法来更新插入的列,但是 - 没有运气。 因此,在谷歌上搜索时发现了一个链接..

  1. 删除了错误插入的列
  2. 使用身份开/关使用强制插入(如下所述)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column -如何更新an.aspx的值

I saw a good article which helped me out at the last moment .. I was trying to insert few rows in a table which had identity column but did it wrongly and have to delete back. Once I deleted the rows then my identity column got changed . I was trying to find an way to update the column which was inserted but - no luck. So, while searching on google found a link ..

  1. Deleted the columns which was wrongly inserted
  2. Use force insert using identity on/off (explained below)

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

煮酒 2024-07-24 06:54:30

非常好的问题,首先我们需要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

Very nice question, first we need to on the IDENTITY_INSERT for the specific table, after that run the insert query (Must specify the column name).

Note: After edit the the identity column, don't forget to off the IDENTITY_INSERT. If you not done, you cannot able to Edit the identity column for any other table.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文