Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server, Wie setze ich das automatische Inkrement nach dem Erstellen einer Tabelle ohne Datenverlust?

Ändern der IDENTITY Eigenschaft ist wirklich nur eine Änderung der Metadaten. Um die Metadaten jedoch direkt zu aktualisieren, müssen Sie die Instanz im Einzelbenutzermodus starten und mit einigen Spalten in sys.syscolpars herumspielen und ist undokumentiert/nicht unterstützt und nichts, was ich empfehlen würde oder worüber ich zusätzliche Details geben werde.

Für Leute, die auf diese Antwort auf SQL Server 2012+ stoßen, wäre der bei weitem einfachste Weg, dieses Ergebnis einer automatisch inkrementierenden Spalte zu erreichen, das Erstellen einer SEQUENCE Objekt und setzen Sie den next value for seq als Spaltenvorgabe.

Alternativ oder für frühere Versionen (ab 2005) zeigt die in diesem Connect-Element gepostete Problemumgehung eine vollständig unterstützte Möglichkeit, dies zu tun, ohne dass Datengrößenoperationen mit ALTER TABLE...SWITCH erforderlich sind . Auch hier auf MSDN gebloggt. Obwohl der Code, um dies zu erreichen, nicht sehr einfach ist und es Einschränkungen gibt - wie zum Beispiel, dass die zu ändernde Tabelle nicht das Ziel einer Fremdschlüssel-Einschränkung sein kann.

Beispielcode.

Testtabelle ohne identity einrichten Spalte.

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

Ändern Sie es, um eine identity zu erhalten Spalte (mehr oder weniger sofort).

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;

Testen Sie das Ergebnis.

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

Gibt

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

Aufräumen

DROP TABLE dbo.tblFoo