programing

SQL Server에서 ID 열을 업데이트하는 방법

topblog 2023. 4. 8. 07:52
반응형

SQL Server에서 ID 열을 업데이트하는 방법

큰 번호의 SQL Server ID로 되었기 때문에 .10010을 하다200파운드레코드가 증가하기 전에 이 문제를 수정하고 싶습니다.

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

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

업데이트 문이 있는 다른 열에서 수행할 수 있는 작업과 달리 SQL Server에서는 ID 열을 업데이트할 수 없습니다.

비슷한 종류의 요구사항을 달성할 수 있는 몇 가지 대안이 있지만.

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

테이블의 현재 ID 값을 확인하고 필요한 경우 ID 값을 변경하는 DBCC CHECKIDENT를 사용합니다.

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

ID 사용_INSERT: 명시적 값을 테이블의 ID 열에 삽입할 수 있습니다.

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

질문을 맞췄다면 이렇게 하고 싶다.

update table
set identity_column_name = some value

그것을 되지 않습니다. 씀드드, 것것 let let let let let let let let let 가 있을 수 때문입니다. 그리고 그것을 사용하는 것은 권장되지 않을 수도 있습니다.foreign key관련지어져 있습니다.

이렇게. 도 꼭 한 번 해 주세요.back-up

스텝 1-테이블의 설계 뷰 선택

여기에 이미지 설명 입력

2단계 - ID 열 끄기

여기에 이미지 설명 입력

, 그럼 에는 '어울리지 않다'를 사용하시면 .update

, 이제redo및 [ on ]의 [Turn on identity column]의 [ID]의 [Turn]를 합니다.

언급

할 필요가 있다

set identity_insert YourTable ON

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

삽입이 완료되면 identity_insert를 꺼야 합니다.

set identity_insert YourTable OFF
--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

다음을 사용해 보십시오.

DBCC CHECKIDENT ('YourTable', RESEED, 1);
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

ID_를 사용하는 경우sql에서는 열 이름을 지정하지 않고 삽입할 수 없으므로 열 이름을 포함하는 것을 잊지 마십시오.

DBCC CHECKIDENT(table_name, RESEED, value)

table_name = 값을 재설정할 테이블을 제공합니다.

value = ID 열을 1로 시작하려면 초기값이 0이어야 합니다.

ID 열 없이 새 테이블에 테이블을 복사합니다.

    select columns into newtable from yourtable

ID 열을 새 시드를 사용하여 새 테이블에 추가하고 기본 키로 만듭니다.

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

를 사용하여 ID 열에 값을 삽입할 수도 있습니다.

예:

SET IDENTITY_INSERT dbo.Tool ON
GO

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

몇 가지 ID를 업데이트해야 하는 것과 같은 문제가 있었습니다(그 ID를 10k 늘려야 했습니다).

set identity_insert YourTable ON

INSERT INTO YourTable 
   ([ID]
   ,[something1]
   ,[something2]
   ,[something3])
SELECT 
   ([ID] + 10000)
   ,[something1]
   ,[something2]
   ,[something3]) 
FROM YourTable
WHERE something1 = 'needs updeted id' 
   AND something2 = 'some other condition'

set identity_insert YourTable OFF

DELETE FROM YourTable 
WHERE ID >= 'your old ID From' 
   AND ID <= 'Your old ID To' 

이치노논리를 합니다. 다른 키 이 키를 에야 이이논 hope from from from from from 에서 삭제할 수 .저의 경우는, 다른 테이블과의 PK-FK 키 접속도 있었습니다.그것은, 그 테이블들을 갱신하고 나서, 다음에 삭제할 수 있게 되었습니다.'YourTable'원래 행

이에 대한 답변이 이미 있다는 것을 알고 있습니다. SQL 쿼리를 예로 남겨두고 싶습니다.

지금까지 본 것처럼 몇 가지 방법이 있지만, 가장 빠르고 좋은 방법은 다음과 같습니다.

identity 열에 등록된 열과 반드시 동일하지는 않은 카운터가 있습니다. 다음 SQL 명령을 사용하여 이 카운터의 값을 확인할 수 있습니다.

DBCC CHECKIDENT('tableName', NORESEED);

그러면 아이덴티티 컬럼을 편집할 수 없지만, 카운터를 필요한 번호만큼 빼고 다시 등록하는 것이 좋습니다.카운터를 다시 설치하려면 다음 명령을 사용합니다.

DBCC CHECKIDENT('tableName', RESEED, desiredNumber);
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

그러나 위의 코드는 기본 키와 외부 키 관계가 없는 경우에만 작동합니다.

Command Builder를 사용하여 C# 프로그래머를 위한 완벽한 솔루션

먼저 다음 사실을 알아야 합니다.

  • 어떤 경우에도 ID 열은 수정할 수 없으므로 행을 삭제하고 새 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 ();
}

업데이트는 허용되지 않지만 가능합니다.

  • 올바른 키로 새 데이터 삽입
  • 레지 삭제

import: 모든 필드를 샘플에 삽입하여 선언해야 합니다.reg 5를 4로 변경해야 합니다.

    set IDENTITY_INSERT Gastos_ReclamacionCausa on
insert into Gastos_ReclamacionCausa
    (IDCausa,TextoCombo,Asunto,Mensaje,EsBaja)
select 4,TextoCombo,Asunto,Mensaje,EsBaja from Gastos_ReclamacionCausa where idcausa=5
delete from  Gastos_ReclamacionCausa where idcausa = 5
set IDENTITY_INSERT Gastos_ReclamacionCausa off

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

먼저 테이블의 새로운 현재 ID 값을 NEW_RESEED_로 설정합니다.가치

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

그 후 를 사용할 수 있습니다.

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

NEW_RESEED_로 시작하는 새로운 IDCol 값을 사용하여 모든 레코드가 복제됩니다.VALUE. 그러면 외부 키 참조를 제거/이동한 후 더 높은 ID 값 중복 행을 제거할 수 있습니다.

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

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

그런 다음 이전 db를 삭제하고 새 db의 이름을 이전 db 이름으로 변경합니다.주의: 이 column1과 column2는 이전 테이블에서 새 테이블에 유지할 모든 열을 나타냅니다.

다음을 수행했습니다.

  1. 관련 데이터를 임시 저장소로 이동
  2. 기본 키/아이덴티티 열 값 업데이트(제약 조건 삭제 및 생성)
  3. 새로운 외부 키 값을 사용하여 관련 데이터 재삽입

스토어드 프로시저로 솔루션을 포장했습니다.

CREATE PROCEDURE [dbo].[UpdateCustomerLocationId]
    @oldCustomerLocationId INT,
    @newCustomerLocationId INT
AS
  /* 
    Updates CustomerLocation.CustomerLocationId @oldCustomerLocationId to @newCustomerLocationId
    
    Example:
        EXEC [dbo].[UpdateCustomerLocationId] 
            @oldCustomerLocationId = 6154874, 
            @newCustomerLocationId = 50334;
    */

BEGIN

    SET NOCOUNT ON;
    
    -- exit if @oldCustomerLocationId does not exists
    IF NOT EXISTS (SELECT * FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @oldCustomerLocationId)
    BEGIN
        PRINT CONCAT('CustomerLocationId ''', @oldCustomerLocationId, ''' (@oldCustomerLocationId) does not exist in dbo.CustomerLocation');
        RETURN 1; -- 0 = success, > 0 = failure
    END

    -- exit if @newCustomerLocationId already exists
    IF EXISTS (SELECT * FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @newCustomerLocationId)
    BEGIN
        PRINT CONCAT('CustomerLocationId ''', @newCustomerLocationId, ''' (@newCustomerLocationId) already exists in dbo.CustomerLocation');
        RETURN 2; -- 0 = success, > 0 = failure
    END
    

    BEGIN TRAN;


        BEGIN -- MOVE related data into temporary storage

            IF EXISTS (SELECT * FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId) BEGIN
    
                IF OBJECT_ID('tempdb..#CustomerLocationData') IS NOT NULL
                    DROP TABLE #CustomerLocationData;

                SELECT * INTO #CustomerLocationData FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId;
                DELETE t FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId;

            END

        END


        BEGIN -- UPDATE dbo.CustomerLocation

            -- DROP CONSTRAINTs
            ALTER TABLE [dbo].[CustomerLocation] DROP CONSTRAINT [UC_CustomerLocation];

            -- INSERT OLD record with new CustomerLocationId
            SET IDENTITY_INSERT dbo.CustomerLocation ON;

            INSERT INTO dbo.CustomerLocation
            (
                CustomerLocationId, CustomerId, LocationId, CustomerLocationIdent, CustomerLocationIdent2, LocationIdent, LocationName, CustomerDistrictId, 
                CustomerLocationGUID, UpdatedOn, IssueManager, EnrollSelfMonitoring, TemperatureControlDeadlineHour, CreatedOn, OperationBegin, ActiveCustomer, 
                Comments, LocationName2, ParentGroup, TempString1, TempString2, TempString3, TempString4, TempString5, AutoInheritFromLocation, ClassificationPrimary
            )
            SELECT @newCustomerLocationId AS CustomerLocationId, CustomerId,LocationId, CustomerLocationIdent, CustomerLocationIdent2, LocationIdent, LocationName, CustomerDistrictId,
                CustomerLocationGUID, UpdatedOn, IssueManager, EnrollSelfMonitoring, TemperatureControlDeadlineHour, CreatedOn, OperationBegin, ActiveCustomer,
                Comments,LocationName2, ParentGroup, TempString1, TempString2, TempString3, TempString4, TempString5, AutoInheritFromLocation, ClassificationPrimary
            FROM dbo.CustomerLocation 
            WHERE CustomerLocationId = @oldCustomerLocationId;

            SET IDENTITY_INSERT dbo.CustomerLocation OFF;

            -- DELETE OLD record
            DELETE cl FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @oldCustomerLocationId;

            -- ADD CONSTRAINTS
            ALTER TABLE [dbo].[CustomerLocation] ADD CONSTRAINT [UC_CustomerLocation] UNIQUE NONCLUSTERED ([CustomerId], [LocationId]);

        END


        BEGIN -- re-INSERT related data from temporary storage

            IF OBJECT_ID('tempdb..#CustomerLocationData') IS NOT NULL BEGIN
                SET IDENTITY_INSERT dbo.CustomerLocationData ON;
                INSERT INTO dbo.CustomerLocationData (Guid, CustomerLocationId, CustomerLocationDataTypeId, Date, Category, Data)
                SELECT Guid, @newCustomerLocationId CustomerLocationId, CustomerLocationDataTypeId, Date, Category, Data FROM #CustomerLocationData;
                SET IDENTITY_INSERT dbo.CustomerLocationData OFF;
            END

        END


    COMMIT TRAN;

END

이 문제는 제가 머지를 하고 있던 아이디를 갱신하는 머지를 했기 때문에 발생했습니다.

효과가 없는 예(광대 참고)아이디:

    MERGE ArchitectMain.dbo.BackendClowns AS TGT 
   USING (
    SELECT ClownID
        ,ClownName
        ,Description
        ,Active
        ,EmailSubject
        ,AddedBy
        ,Added
    FROM #temptable1
    ) AS SRC(ClownID, ClownName, Description, Active, EmailSubject, AddedBy, Added)
    ON (TGT.ClownID = SRC.ClownID)
WHEN MATCHED
    THEN
        UPDATE
        SET ClownID = SRC.ClownID
            ,ClownName = SRC.ClownName
            ,Description = SRC.Description
            ,Active = SRC.Active
            ,EmailSubject = SRC.EmailSubject
            ,AddedBy = SRC.AddedBy
            ,Added = SRC.Added;

효과가 있는 예(광대 참고)아이디:

MERGE ArchitectMain.dbo.BackendClowns AS TGT
USING (
    SELECT ClownID
        ,ClownName
        ,Description
        ,Active
        ,EmailSubject
        ,AddedBy
        ,Added
    FROM #temptable1
    ) AS SRC(ClownID, ClownName, Description, Active, EmailSubject, AddedBy, Added)
    ON (TGT.ClownID = SRC.ClownID)
WHEN MATCHED
    THEN
        UPDATE
        SET ClownName = SRC.ClownName
            ,Description = SRC.Description
            ,Active = SRC.Active
            ,EmailSubject = SRC.EmailSubject
            ,AddedBy = SRC.AddedBy
            ,Added = SRC.Added;
            

이 솔루션은 ALTER TABLE SWITCH 에 의존합니다.이 매뉴얼은 파티션에 매우 중점을 두고 있지만 파티션 없이 여기에 적용할 수 있습니다.테이블 간에 데이터를 매우 빠르게 이동할 수 있습니다.많은 제약사항이 있지만 그 목록에 대한 한 가지 주목할 만한 예외는 다음과 같습니다.

IDENTY 속성은 고려되지 않습니다.

즉, ALTER TABLE SWITCH 문을 사용하여 대상이 소스와 동일한 방식으로 정의된 ID가 없는 경우에도 한 테이블에서 다른 테이블로 데이터를 이동할 수 있습니다.

이 시나리오에서는 ID 열이 외부 키로 참조되지 않았습니다.그렇지 않은 경우에도 이 솔루션을 사용할 수 있지만 참조 테이블의 외부 키 값을 추가로 업데이트해야 합니다.

  1. 다음 절차를 수행하여 해당 테이블의 스크립트를 조정합니다.
    1. 새(임시) 이름을 선택합니다.
    2. 모든 테이블 제약조건에 고유한 이름을 지정합니다.
    3. ID 정의를 삭제합니다.

여기에 이미지 설명 입력

  1. 다음 문을 실행하여 기존 테이블에서 위에서 작성한 새로운 임시 테이블로 데이터를 이동합니다.
ALTER TABLE <EXISTING> SWITCH TO <NEW>;
  1. 테이블 이름을 삽입하고 필요에 따라 열 이름을 조정한 후 다음 문을 실행합니다.그러면 ID가 압축되어 1부터 공백 없이 시작됩니다.이것은 아마도 완료하는 데 가장 오랜 시간이 걸리는 단계일 것입니다.
WITH ids as
(
    SELECT
        ID,
        ROW_NUMBER() OVER (ORDER BY ID) [NewID]
    FROM
        <NEW>
)
UPDATE
    ids
SET
    ID = ids.[NewID];
  1. 다음 문을 실행하여 데이터를 임시 테이블에서 기존 테이블로 다시 스왑합니다.
ALTER TABLE SWITCH <NEW> TO <EXISTING>;
  1. 새로운 ID 값이 테이블 상단에서 이어지도록 ID 열을 다시 설치했다.
DBCC CHECKIDENT ('dbo.FeeItem', RESEED, 0); --Set it to a value that is too low.
DBCC CHECKIDENT ('dbo.FeeItem', RESEED); --Will automatically update it to the maximum value that currently exists in the table.
DBCC CHECKIDENT ('dbo.FeeItem', NORESEED); --Will describe how the identity ends up so that we can check it.
  1. 이제 새 임시 테이블은 내려놓으세요

프라이머리 키의 값을 다른 번호(예:123 -> 1123)로 변경할 필요가 있는 경우.ID 속성은 PK 값 변경을 차단합니다.Identity_insert 설정이 작동하지 않습니다.단계적 삭제가 있는 경우(참조 무결성 검사를 해제하지 않는 한) 삽입/삭제는 권장되지 않습니다.

편집: 새로운 버전의 SQL에서는 syscolumns 엔티티를 변경할 수 없기 때문에 솔루션의 일부는 어려운 방법으로 변경해야 합니다.대신 프라이머리 키에서 ID를 삭제하는 방법에 대해서는 다음 SO를 참조하십시오.테이블의 열에서 ID 제거 이 스크립트는 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을 동일한 열 이름을 기반으로 작성하기 위해 짧은 스크립트를 작성했습니다(내 경우 Case를 늘려야 했습니다).아이디: 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

마지막으로 참조 무결성을 다시 활성화하고 프라이머리 키의 Identity 열을 다시 활성화하십시오.

주의: 이 질문들에 대해 이유를 묻는 사람들이 있습니다.내 경우 두 번째 운영 인스턴스의 데이터를 마스터 DB에 병합해야 두 번째 인스턴스를 종료할 수 있습니다.모든 PK/FK 운영 데이터가 충돌하지 않도록 하기만 하면 됩니다.메타 데이터 FK는 동일합니다.

언급URL : https://stackoverflow.com/questions/19155775/how-to-update-identity-column-in-sql-server

반응형