sql >> Databáze >  >> RDS >> Sqlserver

Jak přidat sloupec identity do existující databázové tabulky, která má velký počet řádků

Celkový proces bude pravděpodobně mnohem pomalejší s větší celkovou režií zamykání, ale pokud vás zajímá pouze velikost protokolu transakcí, můžete zkusit následující.

  1. Přidejte sloupec bez identity celého čísla s povolenou hodnotou null (mění se pouze metadata).
  2. Napište kód, který toto aktualizuje jedinečnými sekvenčními celými čísly v dávkách. Tím se sníží velikost každé jednotlivé transakce a sníží se velikost protokolu (za předpokladu jednoduchého modelu obnovy). Můj kód níže to dělá v dávkách po 100, doufejme, že máte existující PK, kterou můžete využít k navázání tam, kde jste skončili, spíše než opakované skenování, které bude ke konci trvat stále déle.
  3. použijte ALTER TABLE ... ALTER COLUMN pro označení sloupce jako NOT NULL . To bude vyžadovat, aby byla celá tabulka uzamčena a naskenována pro ověření změny, ale nebude vyžadovat mnoho protokolování.
  4. Použijte ALTER TABLE ... SWITCH aby se sloupec stal sloupcem identity. Toto je pouze změna metadat.

Příklad kódu níže

/*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. Django 1.8 Migrace s Postgres BDR 9.4.1

  2. Jak vytvořit blog v PHP a MySQL databázi - Backend

  3. PHP PDO:jak opětovná příprava příkazu ovlivní výkon

  4. Jak mohu filtrovat data v mřížce Apex, abych zobrazil určité věci pro určité skupiny uživatelů?