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

SQL Server, Jak ustawić automatyczny przyrost po utworzeniu tabeli bez utraty danych?

Zmiana IDENTITY właściwość jest tak naprawdę tylko zmianą metadanych. Ale bezpośrednie zaktualizowanie metadanych wymaga uruchomienia instancji w trybie pojedynczego użytkownika i grzebania w niektórych kolumnach w sys.syscolpars i jest nieudokumentowane/nieobsługiwane i nie jest czymś, co poleciłbym lub podałbym dodatkowe szczegóły.

Dla osób, które natkną się na tę odpowiedź w SQL Server 2012+ zdecydowanie najłatwiejszym sposobem osiągnięcia tego wyniku kolumny autoinkrementacji byłoby utworzenie SEQUENCE obiekt i ustaw next value for seq jako domyślna kolumna.

Alternatywnie lub w przypadku poprzednich wersji (od 2005 r.) obejście opisane w tym elemencie connect pokazuje w pełni obsługiwany sposób wykonania tego bez potrzeby określania rozmiaru operacji na danych przy użyciu ALTER TABLE...SWITCH . O tym pisałem również na blogu MSDN tutaj. Chociaż kod do osiągnięcia tego nie jest bardzo prosty i istnieją ograniczenia - na przykład zmieniana tabela nie może być celem ograniczenia klucza obcego.

Przykładowy kod.

Ustaw tabelę testową bez identity kolumna.

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

Zmień go, aby miał identity kolumna (mniej lub bardziej natychmiastowa).

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;

Przetestuj wynik.

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

Daje

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

Posprzątaj

DROP TABLE dbo.tblFoo


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Musisz zadeklarować zmienną skalarną @Id?

  2. Dlaczego używanie kursorów w SQL Server jest uważane za złą praktykę?

  3. SQL Server - brak NATURAL JOIN / x JOIN y USING(pole)

  4. Jak wybrać datę bez czasu w SQL

  5. Różnica między sys.columns, sys.system_columns i sys.all_columns w programie SQL Server