[sql] 테이블의 열에서 ID 제거

5GB 테이블 (거의 5 억 행)이 있고 열 중 하나에서 ID 속성을 제거하려고하지만 SSMS를 통해이 작업을 수행하려고하면 시간이 초과됩니다.

T-SQL을 통해이 작업을 수행 할 수 있습니까?



답변

IDENTITY일단 설정되면 사양을 제거 할 수 없습니다 .

전체 열을 제거하려면 :

ALTER TABLE yourTable
DROP COLUMN yourCOlumn;

여기 에 ALTER TABLE 에 대한 정보

데이터를 유지해야하지만 IDENTITY열을 제거 해야하는 경우 다음을 수행해야합니다.

  • 새 열 만들기
  • 기존 IDENTITY열의 데이터를 새 열로 전송
  • 기존 IDENTITY열을 삭제하십시오 .
  • 새 열의 이름을 원래 열 이름으로 바꿉니다.

답변

이 작업을 수행하려면 추가하고 새 열을 채우지 않고 , 열을 재정렬없이 하고, 중단 시간없이 어떤 파티션이 사용되지 않기 때문에 데이터가 테이블에 변경되지 않기 때문에,하자가 기능을 분할하여 마법을 (하지만 당신은 돈 ‘ 엔터프라이즈 에디션 필요) :

  1. 이 테이블을 가리키는 모든 외래 키 제거
  2. 생성 할 테이블을 스크립팅합니다. 예를 들어 ‘MyTable2’, ‘MyIndex2’등과 같은 모든 이름을 바꿉니다. IDENTITY 사양을 제거합니다.
  3. 이제 두 개의 “동일한”테이블이 있어야합니다. 하나는 가득 차고 다른 하나는 IDENTITY없이 비어 있습니다.
  4. 운영 ALTER TABLE [Original] SWITCH TO [Original2]
  5. 이제 원래 테이블이 비어 있고 새 테이블에 데이터가 있습니다. 두 테이블의 메타 데이터를 전환했습니다 (인스턴트).
  6. 원본 (현재 비어있는 테이블)을 삭제하고 exec sys.sp_rename다양한 스키마 개체의 이름을 다시 원래 이름으로 바꾼 다음 외래 키를 다시 만들 수 있습니다.

예를 들면 다음과 같습니다.

CREATE TABLE Original
(
  Id INT IDENTITY PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value ON Original (Value);

INSERT INTO Original
SELECT 'abcd'
UNION ALL
SELECT 'defg';

다음을 수행 할 수 있습니다.

--create new table with no IDENTITY
CREATE TABLE Original2
(
  Id INT PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value2 ON Original2 (Value);

--data before switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

ALTER TABLE Original SWITCH TO Original2;

--data after switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

--clean up 
IF NOT EXISTS (SELECT * FROM Original) DROP TABLE Original;
EXEC sys.sp_rename 'Original2.IX_Original_Value2', 'IX_Original_Value', 'INDEX';
EXEC sys.sp_rename 'Original2', 'Original', 'OBJECT';


UPDATE Original
SET Id = Id + 1;

SELECT *
FROM Original;


답변

외래 및 기본 키 제약 조건이 복잡해 지므로 다음과 같은 방법으로 도움이 될 몇 가지 스크립트가 있습니다.

먼저 임시 이름으로 중복 열을 만듭니다.

alter table yourTable add tempId int NOT NULL default -1;
update yourTable set tempId = id;

다음으로 기본 키 제약 조건의 이름을 가져옵니다.

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable';

이제 열에 대한 기본 키 제약 조건을 삭제하십시오.

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;

외래 키가 있으면 실패하므로 외래 키 제약 조건을 삭제하십시오. 이 작업을 실행하는 테이블을 추적하여 나중에 제약 조건을 다시 추가 할 수 있습니다 !!!

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable';
alter table otherTable drop constraint fk_otherTable_yourTable;
commit;
..

모든 외래 키 제약 조건이 제거되면 PK 제약 조건을 제거하고 해당 열을 삭제하고 임시 열의 이름을 바꾸고 해당 열에 PK 제약 조건을 추가 할 수 있습니다.

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;
alter table yourTable drop column id;
EXEC sp_rename 'yourTable.tempId', 'id', 'COLUMN';
ALTER TABLE yourTable ADD CONSTRAINT PK_yourTable_id PRIMARY KEY (id)
commit;

마지막으로 FK 제약 조건을 다시 추가합니다.

alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id);
..

엘핀!


답변

나는이 같은 문제가 있었다. GUI를 사용하는 대신 SSMS에서 4 개의 명령문을 사용하며 매우 빠릅니다.

  • 새 열 만들기

    alter table users add newusernum int;

  • 값 복사

    update users set newusernum=usernum;

  • 이전 열 삭제

    alter table users drop column usernum;

  • 새 열의 이름을 이전 열 이름으로 바꿉니다.

    EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';


답변

다음 스크립트는 ‘Id’라는 열의 ID 필드를 제거합니다.

도움이 되었기를 바랍니다.

BEGIN TRAN
BEGIN TRY
    EXEC sp_rename '[SomeTable].[Id]', 'OldId';

    ALTER TABLE [SomeTable] ADD Id int NULL

    EXEC ('UPDATE [SomeTable] SET Id = OldId')

    ALTER TABLE [SomeTable] NOCHECK CONSTRAINT ALL

    ALTER TABLE [SomeTable] DROP CONSTRAINT [PK_constraintName];
    ALTER TABLE [SomeTable] DROP COLUMN OldId
    ALTER TABLE [SomeTable] ALTER COLUMN [Id] INTEGER NOT NULL
    ALTER TABLE [SomeTable] ADD CONSTRAINT PK_JobInfo PRIMARY KEY (Id)

    ALTER TABLE [SomeTable] CHECK CONSTRAINT ALL

    COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN
    SELECT ERROR_MESSAGE ()
END CATCH


답변

식별 열 이름을 모르는 경우 벨로우 코드가 정상적으로 작동 합니다.

.NET과 같은 새 임시 테이블에 데이터를 복사해야합니다 Invoice_DELETED. 다음에 사용할 때 :

insert into Invoice_DELETED select * from Invoice where ...


SELECT t1.*
INTO Invoice_DELETED
FROM Invoice t1
LEFT JOIN Invoice ON 1 = 0
--WHERE t1.InvoiceID = @InvoiceID

자세한 설명은 https://dba.stackexchange.com/a/138345/101038을 참조하십시오.


답변

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

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