sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server, ¿cómo configurar el incremento automático después de crear una tabla sin pérdida de datos?

Cambiando la IDENTITY La propiedad es realmente un cambio de metadatos solamente. Pero actualizar los metadatos directamente requiere iniciar la instancia en modo de usuario único y jugar con algunas columnas en sys.syscolpars y no está documentado/no es compatible y no es algo que recomendaría o sobre lo que daré detalles adicionales.

Para las personas que encuentran esta respuesta en SQL Server 2012+, la forma más fácil de lograr este resultado de una columna de incremento automático sería crear una SEQUENCE objeto y establezca el next value for seq como columna predeterminada.

Alternativamente, o para versiones anteriores (desde 2005 en adelante), la solución publicada en este elemento de conexión muestra una forma completamente compatible de hacer esto sin necesidad de operaciones de tamaño de datos usando ALTER TABLE...SWITCH . También se publicó en un blog sobre MSDN aquí. Aunque el código para lograr esto no es muy simple y existen restricciones, como que la tabla que se cambia no puede ser el objetivo de una restricción de clave externa.

Código de ejemplo.

Configurar tabla de prueba sin identity columna.

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

Modificarlo para tener una identity columna (más o menos instantánea).

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;

Prueba el resultado.

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

Da

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

Limpiar

DROP TABLE dbo.tblFoo