프로그래밍 방식으로 ID 열 값을 변경하는 방법은 무엇입니까?


160

Testcolumn 이있는 테이블이있는 MS SQL 2005 데이터베이스가 ID있습니다. IDID 열입니다.

이 테이블에 행이 있고 모든 해당 ID 자동 증분 값이 있습니다.

이제이 표의 모든 ID를 다음과 같이 변경하고 싶습니다.

ID = ID + 1

그러나이 작업을 수행하면 오류가 발생합니다.

ID 열 'ID'를 업데이트 할 수 없습니다.

나는 이것을 시도했다 :

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

그러나 이것은 문제를 해결하지 못합니다.

이 열에 ID를 설정해야하지만 때때로 값을 변경해야합니다. 그래서 내 질문은이 작업을 수행하는 방법입니다.

답변:


220

당신은 필요

set identity_insert YourTable ON

그런 다음 행을 삭제하고 다른 ID로 다시 삽입하십시오.

삽입을 완료하면 identity_insert를 끄는 것을 잊지 마십시오

set identity_insert YourTable OFF

133
이 설정은 데이터를 삽입 할 때만 작동하며 업데이트 할 때는 작동하지 않습니다. UPDATE 문은 여전히 ​​실패합니다.
Husein Roncevic

31
업데이트하려면 삭제하고 다시 삽입해야합니다. 다른 방법은 없습니다.
ashes999

1
@ MartinSmith 솔루션이 너무 길어 보입니다. 두 단계 (ID-OFF, 삭제 / 삽입, ID-ON)로 할 수있는 것이 훨씬 더 효과적입니다.
ashes999

3
@ ashes999 2 단계가 아닌 4 단계입니다. 제 답변은 한 번만 더 있습니다 (테이블 만들기, 스위치, 업데이트, 전환, 삭제). 많은 행이 관련되어 있으면 업데이트가 훨씬 효율적일 수 있으며 삽입을 삭제하십시오. 또한 삭제 된 행을 어디에서 잡고 있습니까? #temp삭제 한 테이블이 다른 단계 인 경우 여기에 포함되지 않습니다.
Martin Smith

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

1
매우 매끄 럽습니다. 매일 새로운 것을 배우십시오 (BTW는 SQLExpress에서 이것을 테스트했지만 SWITCH TO에도 불구하고 파티션을 사용하지 않는 것 같습니다). 표는 정확히 일치해야합니다 (색인, FK 등)
Mark Sowul

1
PK, FK, 인덱스 및 뷰가 원래 테이블에 구축 된 경우 스위치 방법이 작동합니까? 이 방법을 사용하면 중단됩니까?
tj

1
임시 테이블 스크립트를 만들 때 @tj는 모든 인덱스와 제약 조건을 포함하여 소스 테이블을 출력합니다. 그런 다음 충돌을 피하기 위해 테이블 ​​이름과 제약 조건을 변경하십시오. 인덱싱되거나 스키마 바인딩되지 않은 뷰는 문제를 일으키지 않습니다.
Martin Smith

테이블에 전체 텍스트 검색 인덱스가 있으면 작동하지 않습니다. 나는 그것을 제거하고 나중에 다시 만들 수 있다고 가정하지만 테스트하지는 않았습니다.
youn

26

SQL Server 2005 관리자의 UI를 통해 열을 변경하여 열의 자동 번호 (ID) 속성을 제거합니다 (테이블을 마우스 오른쪽 버튼으로 클릭하여 선택하고 "디자인"선택).

그런 다음 쿼리를 실행하십시오.

UPDATE table SET Id = Id + 1

그런 다음 autonumber 속성을 다시 열에 추가하십시오.


3
수동으로 변경하는 경우 관리자에게 변경에 대한 SQL 스크립트를 생성하도록 요청할 수 있습니다 (테이블 디자이너 메뉴, 변경 스크립트 생성). 이 변경을 위해 새 테이블을 작성하고 데이터를 복사 한 다음 원본을 삭제합니다.
Robin Bennett

2
@tomaszs - 물리적으로 전혀 테이블을 다시 작성하지 않습니다 (이 그렇게 두 번 할 것)으로도 더 효율적입니다 코드 예제는 내 말 대답에 여기
마틴 스미스

ID를 다시 추가 할 수 없습니다. 당신 은요? stackoverflow.com/questions/1049210/…
Tomas Kubes

감사. 이것은 완벽했다. 테이블에 1 개의 행이있어 알 수 없었으므로 테이블에 대한 부트 스트랩 스크립트의 IdAuto Identity 값이 1
Shiva

18

먼저 해당 문제에 대한 IDENTITY_INSERT 설정을 켜거나 끄면 필요한 값에 맞지 않습니다 (플러그 갭과 같은 새 값을 삽입하는 데 사용됨).

GUI를 통해 작업을 수행하면 임시 테이블이 생성되고 ID 필드없이 모든 데이터가 새 테이블에 복사되고 테이블 이름이 바뀝니다.


9

임시 테이블을 사용하여 수행 할 수 있습니다.

아이디어

  • 제약 조건 비활성화 (ID가 외래 키로 참조되는 경우)
  • 새 ID로 임시 테이블을 만듭니다.
  • 테이블 내용을 삭제
  • 복사 한 테이블에서 원래 테이블로 데이터를 다시 복사
  • 사전에 비활성화 된 제약 조건 활성화

SQL 쿼리

하자가 당신의 말을 test테이블에 두 개의 추가 열 (가 column2column3)과 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;

그게 다야.


6

DBCC CHECKIDENT ( 'databasename.dbo.orders', RESEED, 999)이 명령으로 ID 열 번호를 변경할 수 있으며 원하는 모든 숫자에서 해당 필드 번호를 시작할 수 있습니다. 예를 들어 내 명령에서 시작을 요청합니다. 1000 (999 + 1)이면 충분할 것입니다 ... 행운


4

열이 PK가 아닌 경우 항상 증가 된 숫자로 테이블에 새 열을 작성하고 원본을 제거한 다음 새 열을 이전 열로 변경할 수 있습니다.

왜이 작업을 수행 해야하는지 궁금합니다 ... Identity 열로 퍼트해야했던 대부분은 숫자를 채우는 것이었고 DBCC CHECKIDENT (tablename, RESEED, newnextnumber)를 사용했습니다.

행운을 빕니다!


1

ID 열에 연결된 개체 / 관계를 중심으로 회전하는 여러 요인에 따라 ID 수정이 실패 할 수 있습니다. id가 거의 변경되지 않으면 db 디자인이 문제가되는 것처럼 보입니다 (귀하의 이유가 있고 변경 사항이 있음을 확신합니다). ID를 수시로 변경 해야하는 경우 직접 관리하고 현재 값에서 생성 할 수있는 기본 키 / 자동 번호가 아닌 새로운 더미 ID 열을 만드는 것이 좋습니다. 또는 신원 삽입 허용에 문제가있는 경우 위의 Chrisotphers 아이디어가 다른 제안 일 것입니다.

행운을 빕니다

추신 : 순서대로 실행중인 순서대로 목록의 값을 이미 ID 목록에있는 항목으로 업데이트하려고하기 때문에 실패하지 않습니까? 빨대에 쥐고, 아마도 행 수 + 1을 더한 다음 작동하면 행 수를 뺍니다 : -S


1

ID를 가끔 변경해야 할 경우 ID 열을 사용하지 않는 것이 가장 좋습니다. 과거에는 각 테이블의 다음 ID를 추적하는 '카운터'테이블을 사용하여 자동 번호 필드를 수동으로 구현했습니다. IIRC는 ID 열이 SQL2000에서 데이터베이스 손상을 일으켰지 만 ID를 변경할 수 있었기 때문에 테스트에 유용하기 때문에이를 수행했습니다.


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

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_insertoff로 설정하지 않으면 다음 오류가 발생합니다.

IDENTITY_INSERT가 OFF로 설정되어 있으면 'Test'테이블에서 ID 열에 명시 적 값을 삽입 할 수 없습니다.


0

나는 마지막 순간에 나에게 도움이 된 좋은 기사를 보았습니다.. ID 열이있는 테이블에 몇 개의 행을 삽입하려고했지만 잘못하고 삭제해야합니다. 행을 삭제하면 ID 열이 변경되었습니다. 삽입 된 열을 업데이트하는 방법을 찾으려고했지만 운이 없습니다. 그래서 Google에서 검색하는 동안 ..

  1. 잘못 삽입 된 열을 삭제했습니다.
  2. ID 켜기 / 끄기를 사용하여 강제 삽입 사용 (아래 설명)

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


1
그래도 질문에 실제로 대답했는지 확실하지 않습니다.
Andrew Barber

0

아주 좋은 질문입니다. 먼저 삽입 쿼리를 실행 한 후에 특정 테이블 대해 IDENTITY_INSERT를 사용해야 합니다 (열 이름을 지정해야 함).

참고 : ID 열을 수정 한 후에 는 IDENTITY_INSERT 를 해제해야 합니다. 완료하지 않으면 다른 테이블의 ID 열을 편집 할 수 없습니다.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.