SQL Server에서 ID 열을 업데이트하는 방법은 무엇입니까?


196

SQL Server 데이터베이스가 있고 큰 숫자로 시작 10010하고 다른 테이블과 관련되어 있기 때문에 ID 열을 변경하고 싶습니다 . 이제 200 개의 레코드가 있으며 레코드가 증가하기 전에이 문제를 해결하려고합니다.

이 항목을 변경하거나 재설정하는 가장 좋은 방법은 무엇입니까?

답변:


270

신원 열을 업데이트 할 수 없습니다.

SQL Server에서는 update 문을 사용하여 다른 열로 수행 할 수있는 것과 달리 ID 열을 업데이트 할 수 없습니다.

비슷한 종류의 요구 사항을 달성하기위한 몇 가지 대안이 있지만.

  • 새 레코드에 대해 ID 열 값을 업데이트해야하는 경우

테이블의 현재 ID 값을 확인하고 필요한 경우 ID 값을 변경하는 DBCC CHECKIDENT 사용하십시오 .

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • 기존 레코드에 대한 ID 열 값을 업데이트해야하는 경우

사용 IDENTITY_INSERT 명시 적 값을 허용하는 테이블의 식별 컬럼에 삽입합니다.

SET IDENTITY_INSERT YourTable {ON|OFF}

예:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF

6
DBCC 다음 새 레코드를 재설정하지만 기존 레코드를 변경하려고합니다.
Abdulsalam Elsharif

예를 들어 주시겠습니까?
Abdulsalam Elsharif

38
@sachin 이것은 기존의 IDENTITY를 수동으로 삽입하지 않습니다
Phill Greggan

3
@PhillGreggan 예, 이것이 이것을 달성하는 가장 좋은 해결책입니다. 일반 항목을 업데이트 할 때 ID 열을 업데이트 할 수 없습니다.
Sachin

17
이 수락 된 답변은 질문에 답변하지 않으며, 이는 ID 열 을 업데이트 하는 방법입니다 (예 :) UPDATE YourTable SET IdentityCol = 13. SET IDENTITY_INSERT YourTable ONUPDATE가 아닌 INSERT 만 허용합니다.
Ian Boyd

62

질문이 바로 있다면 다음과 같은 일을하고 싶습니다.

update table
set identity_column_name = some value

쉬운 과정이 아니며 관련 과정이있을 수 있으므로 사용하지 않는 것이 좋습니다 foreign key.

그러나 여기 그것을 할 단계는, 테이크 바랍니다 back-up테이블을

1 단계-테이블의 디자인 뷰 선택

여기에 이미지 설명을 입력하십시오

2 단계-ID 열 끄기

여기에 이미지 설명을 입력하십시오

이제 update쿼리를 사용할 수 있습니다 .

이제 redo1 단계와 2 단계에서 ID 열을 켭니다.

참고


1
나는이 테이블과 관련된 또 다른 테이블이 나는 일이 내가 할 수 없어
압둘 Elsharif

4
그러므로 그 진술 은 바람직하지 않다 :)
Luv

3
@AbdusalamElsherif 그러나 ID 열을 변경하는 방법을 물었습니다.
paparazzo

@luv 적어도 당신은 그 질문에 대답했습니다
Phill Greggan

개발 데이터베이스에서 ID를 설정하기 위해이 절차를 사용합니다. 어쨌든 내가 할 수있는 명령이 있다면 좋을 것입니다. 그러나 이것은 효과가 있습니다.
Jeff Davis

56

당신은 필요

set identity_insert YourTable ON

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

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

set identity_insert YourTable OFF

이것은 열의 ID를 끄는 것보다 훨씬 쉽고 안전합니다!
수호자 1

이것은 적은 수의 레코드에 대해 더 안전하고 쉬우나 질문에 제대로 대답하지 못합니다. 더 위험하고 때로는 불가능하기는하지만 ID를 끄면 ID 열을 업데이트 할 수 있습니다.
Matthew Hudson

18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO

1
테이블이 매우 큰 경우 성능 팁만으로 테이블에서 삭제를 수행하는 대신 테이블 잘라내기를 수행하십시오. 순간적입니다. 그러나 기록되지 않으므로 잘림으로 다시 돌아 가지 않습니다.
kuklei


5

ID 열이없는 새 테이블에 테이블을 복사하십시오.

    select columns into newtable from yourtable

새로운 시드로 newtable에 ID 열을 추가하고 기본 키로 만듭니다.

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = 재설정하려는 테이블을 제공하십시오.

value = 초기 값은 0으로, ID 열을 1로 시작합니다.


3
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

Identity_Insert를 사용할 때 sql은 열 이름을 지정하지 않고 삽입 할 수 없으므로 열 이름을 포함시키는 것을 잊지 마십시오.


2

또한 SET IDENTITY INSERTID 열에 값을 삽입 할 수 있습니다.

예:

SET IDENTITY_INSERT dbo.Tool ON
GO

그런 다음 필요한 값을 ID 열에 삽입 할 수 있습니다.


1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

그러나 위 코드는 1 차 외래 키 관계가없는 경우에만 작동합니다


1

명령 빌더를 사용하는 C # 프로그래머를위한 완벽한 솔루션

우선, 당신은이 사실을 알아야합니다 :

  • 어쨌든 ID 열을 수정할 수 없으므로 행을 삭제하고 새 ID로 다시 추가해야합니다.
  • 열에서 아이디 속성을 제거 할 수 없습니다 (열로 제거해야 함)
  • .net의 사용자 정의 명령 빌더는 항상 ID 열을 건너 뛰므로이 용도로 사용할 수 없습니다.

따라서 일단 알고 있으면해야합니다. 자체 SQL Insert 문을 프로그래밍하거나 insert 명령 빌더를 소유 한 프로그램을 프로그래밍하십시오. 또는 내가 당신을 위해 프로그래밍 한 것을 사용하십시오. DataTable이 주어지면 SQL 삽입 스크립트를 생성합니다.

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}

0

먼저 DBCC를 사용한 다음 insert를 사용하여이 문제를 해결했습니다. 예를 들어 테이블이

먼저 테이블에서 새로운 현재 ID 값을 NEW_RESEED_VALUE로 설정하십시오.

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

그럼 당신은 사용할 수 있습니다

    insert into MyTable (colA, ColB) select colA, colB from MyTable

NEW_RESEED_VALUE로 시작하는 새 IDCol 값을 사용하지만 모든 레코드가 복제됩니다. 그런 다음 외래 키 참조 (있는 경우)를 제거 / 이동하면 더 높은 ID 값 중복 행을 제거 할 수 있습니다.


1
이것은 괜찮은 아이디어이지만 New_reseed_value는 현재 시드이며 사용할 다음 숫자는 해당 값보다 1이 더 큽니다. 따라서 다음에 삽입 된 행을 ID 10으로하려면 NEW_RESEED_VALUE를 9로 설정해야합니다.
LarryBud

0

다음 코드를 사용하여 새 테이블을 만들 수 있습니다.

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

그런 다음 이전 db를 삭제하고 새 db의 이름을 이전 db의 이름으로 바꿉니다. 참고 : column1 및 column2는 새 테이블에 유지하려는 이전 테이블의 모든 열을 나타냅니다.


0

기본 키 값을 다른 숫자 (예 : 123-> 1123)로 변경해야하는 경우 identity 속성은 PK 값 변경을 차단합니다. Set Identity_insert가 작동하지 않습니다. 계단식 삭제가있는 경우 참조 무결성 검사를 해제하지 않는 한 삽입 / 삭제를 수행하지 않는 것이 좋습니다.

이 스크립트는 PK에서 ID를 해제합니다.

***********************

sp_configure 'allow update', 1
go
reconfigure with override
go


update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go


exec sp_configure 'allow update', 0
go
reconfigure with override
go

***********************

다음으로 외래 키 참조를 업데이트하도록 관계를 설정할 수 있습니다. 그렇지 않으면 관계 시행을 해제해야합니다. 이 SO 링크는 어떻게 T-SQL을 사용하여 외래 키 제약 조건을 일시적으로 비활성화 할 수 있습니까?를 보여줍니다.

이제 업데이트를 할 수 있습니다. 동일한 열 이름을 기반으로 모든 업데이트 SQL을 작성하는 짧은 스크립트를 작성했습니다 (제 경우에는 CaseID를 1,000,000 씩 늘려야했습니다).

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

마지막으로 참조 무결성을 다시 활성화 한 다음 기본 키에서 ID 열을 다시 활성화하십시오.

참고 :이 질문에 대한 사람들이 WHY를 묻는 것을 보았습니다. 필자의 경우 두 번째 인스턴스를 종료 할 수 있도록 두 번째 프로덕션 인스턴스의 데이터를 마스터 DB로 병합해야합니다. 충돌하지 않으려면 모든 PK / FK 작업 데이터가 필요합니다. 메타 데이터 FK는 동일합니다.

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