Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

SQL Server, come impostare l'incremento automatico dopo aver creato una tabella senza perdita di dati?

Modifica del IDENTITY la proprietà è in realtà una modifica solo dei metadati. Ma per aggiornare direttamente i metadati è necessario avviare l'istanza in modalità utente singolo e scherzare con alcune colonne in sys.syscolpars ed è non documentato/non supportato e non è qualcosa che consiglierei o su cui fornirò ulteriori dettagli.

Per le persone che si imbattono in questa risposta su SQL Server 2012+, il modo di gran lunga più semplice per ottenere questo risultato di una colonna con incremento automatico sarebbe creare una SEQUENCE oggetto e imposta il next value for seq come impostazione predefinita della colonna.

In alternativa, o per le versioni precedenti (dal 2005 in poi), la soluzione alternativa pubblicata su questo elemento di connessione mostra un modo completamente supportato per farlo senza alcuna necessità di dimensioni delle operazioni sui dati utilizzando ALTER TABLE...SWITCH . Anche blog su MSDN qui. Sebbene il codice per ottenere ciò non sia molto semplice e ci siano delle restrizioni, ad esempio la modifica della tabella non può essere l'obiettivo di un vincolo di chiave esterna.

Esempio di codice.

Imposta la tabella di test senza identity colonna.

CREATE TABLE dbo.tblFoo 
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)


INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2

Modificalo per avere un'identity colonna (più o meno istantanea).

BEGIN TRY;
    BEGIN TRANSACTION;

    /*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
      set the correct seed in the table definition instead*/
    DECLARE @TableScript nvarchar(max)
    SELECT @TableScript = 
    '
    CREATE TABLE dbo.Destination(
        bar INT IDENTITY(' + 
                     CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1)  PRIMARY KEY,
        filler CHAR(8000),
        filler2 CHAR(49)
        )

        ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
    '       
    FROM dbo.tblFoo
    WITH (TABLOCKX,HOLDLOCK)

    EXEC(@TableScript)


    DROP TABLE dbo.tblFoo;

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


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

Verifica il risultato.

INSERT INTO dbo.tblFoo (filler,filler2) 
OUTPUT inserted.*
VALUES ('foo','bar')

bar         filler    filler2
----------- --------- ---------
10001       foo       bar      

Pulisci

DROP TABLE dbo.tblFoo