Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak dodać kolumnę tożsamości do istniejącej tabeli bazy danych, która ma dużą liczbę wierszy?

Ogólny proces będzie prawdopodobnie znacznie wolniejszy z większym ogólnym obciążeniem związanym z blokowaniem, ale jeśli zależy Ci tylko na rozmiarze dziennika transakcji, możesz wypróbować następujące rozwiązania.

  1. Dodaj kolumnę z liczbą całkowitą dopuszczającą wartość null, która nie jest identyczna (zmiana dotyczy tylko metadanych).
  2. Napisz kod, aby zaktualizować to za pomocą unikalnych sekwencyjnych liczb całkowitych w partiach. Spowoduje to zmniejszenie rozmiaru każdej pojedynczej transakcji i zmniejszenie rozmiaru dziennika (przy założeniu prostego modelu odzyskiwania). Mój kod poniżej robi to w partiach po 100, miejmy nadzieję, że masz istniejącą PK, którą możesz wykorzystać, aby wznowić w miejscu, w którym przerwałeś, zamiast powtarzać skany, które będą trwać coraz dłużej pod koniec.
  3. użyj ALTER TABLE ... ALTER COLUMN aby oznaczyć kolumnę jako NOT NULL . Będzie to wymagało zablokowania i przeskanowania całej tabeli w celu zweryfikowania zmiany, ale nie będzie wymagało dużo rejestrowania.
  4. Użyj ALTER TABLE ... SWITCH aby kolumna była kolumną tożsamości. To jest tylko zmiana metadanych.

Przykładowy kod poniżej

/*Set up test table with just one column*/

CREATE TABLE table_1 ( original_column INT )
INSERT  INTO table_1
        SELECT DISTINCT
                number
        FROM    master..spt_values



/*Step 1 */
ALTER TABLE table_1 ADD id INT NULL



/*Step 2 */
DECLARE @Counter INT = 0 ,
    @PrevCounter INT = -1

WHILE @PrevCounter <> @Counter 
    BEGIN
        SET @PrevCounter = @Counter;
        WITH    T AS ( SELECT TOP 100
                                * ,
                                ROW_NUMBER() OVER ( ORDER BY @@SPID )
                                + @Counter AS new_id
                       FROM     table_1
                       WHERE    id IS NULL
                     )
            UPDATE  T
            SET     id = new_id
        SET @Counter = @Counter + @@ROWCOUNT
    END


BEGIN TRY;
    BEGIN TRANSACTION ;
     /*Step 3 */
    ALTER TABLE table_1 ALTER COLUMN id INT NOT NULL

    /*Step 4 */
    DECLARE @TableScript NVARCHAR(MAX) = '
    CREATE TABLE dbo.Destination(
        original_column INT,
        id INT IDENTITY(' + CAST(@Counter + 1 AS VARCHAR) + ',1)
        )

        ALTER TABLE dbo.table_1 SWITCH TO dbo.Destination;
    '       

    EXEC(@TableScript)


    DROP TABLE table_1 ;

    EXECUTE sp_rename N'dbo.Destination', N'table_1', 'OBJECT' ;


    COMMIT TRANSACTION ;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 
        ROLLBACK TRANSACTION ;
    PRINT ERROR_MESSAGE() ;
END CATCH ;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Szacowanie przyłączeń programu SQL Server przy użyciu zgrubnego wyrównania histogramu

  2. EntityFramework ConnectionString utf8

  3. Używanie merge..output do uzyskania mapowania między source.id i target.id

  4. SQL Server 2017:importowanie danych CSV z systemu Linux do Salesforce za pomocą SSIS

  5. DB_NAME() vs ORIGINAL_DB_NAME() w SQL Server:jaka jest różnica?