it-swarm.com.de

SQL Server, Wie kann das automatische Inkrement nach dem Erstellen einer Tabelle ohne Datenverlust eingestellt werden?

Ich habe eine Tabelle table1 in SQL Server 2008 und darin befinden sich Datensätze. 

Ich möchte, dass die table1_Sno-Spalte des Primärschlüssels eine automatisch inkrementierende Spalte ist. Ist dies ohne Datenübertragung oder Klonen von Tabellen möglich?

Ich weiß, dass ich ALTER TABLE verwenden kann, um eine Spalte für das automatische Inkrementieren hinzuzufügen, aber kann ich einfach die Option AUTO_INCREMENT einer vorhandenen Spalte hinzufügen, die der Primärschlüssel ist?

47
Shankar

Das Ändern der IDENTITY-Eigenschaft ist wirklich nur eine Änderung der Metadaten. Um die Metadaten direkt zu aktualisieren, müssen Sie die Instanz jedoch im Einzelbenutzermodus starten und einige Spalten in sys.syscolpars durcheinander bringen. Sie ist undokumentiert/nicht unterstützt und sollte nicht weiterempfohlen werden.

Für Leute, die diese Antwort auf SQL Server 2012+ finden, ist der einfachste Weg, dieses Ergebnis einer automatisch inkrementierenden Spalte zu erzielen, das Erstellen eines SEQUENCE-Objekts und das Festlegen des next value for seq als Spaltenstandard.

Alternativ oder für frühere Versionen (ab 2005) zeigt die auf this connect item veröffentlichte Problemumgehung eine vollständig unterstützte Möglichkeit, dies zu tun, ohne dass Datenoperationen mit ALTER TABLE...SWITCH erforderlich sind. Auch über MSDN hier gebloggt. Allerdings ist der Code, mit dem dies erreicht wird, nicht sehr einfach und es gibt Einschränkungen. Beispielsweise kann die zu ändernde Tabelle nicht das Ziel einer Fremdschlüsseleinschränkung sein.

Beispielcode.

Testtabelle ohne identity-Spalte einrichten.

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-Spalte zu haben (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
63
Martin Smith

SQL Server: So legen Sie das automatische Inkrement für eine Tabelle mit Zeilen fest:

Bei dieser Strategie werden die Zeilen physisch zweimal kopiert, was bei einer großen Tabelle, die Sie kopieren, sehr viel länger dauern kann. 

Sie können Ihre Daten speichern, die Tabelle mit dem Auto-Inkrement- und Primärschlüssel löschen und neu erstellen und dann die Daten wieder laden. 

Ich werde Sie mit einem Beispiel durchgehen:

Schritt 1, Tabelle foobar erstellen (ohne Primärschlüssel oder Auto-Inkrement):

CREATE TABLE foobar(
    id int NOT NULL,
    name nchar(100) NOT NULL,
)

Schritt 2, füge einige Zeilen ein

insert into foobar values(1, 'one');
insert into foobar values(2, 'two');
insert into foobar values(3, 'three');

Schritt 3, kopiere foobar-Daten in eine temporäre Tabelle:

select * into temp_foobar from foobar

Schritt 4, drop table foobar:

drop table foobar;

Schritt 5, erstellen Sie Ihre Tabelle mit den Eigenschaften Primärschlüssel und Auto-Inkrement neu:

CREATE TABLE foobar(
    id int primary key IDENTITY(1, 1) NOT NULL,
    name nchar(100) NOT NULL,
)

Schritt 6, füge deine Daten aus der temporären Tabelle zurück in foobar ein

SET IDENTITY_INSERT temp_foobar ON
INSERT into foobar (id, name) select id, name from temp_foobar;

Schritt 7, lösche die temporäre Tabelle und überprüfe, ob sie funktioniert:

drop table temp_foobar;
select * from foobar;

Sie sollten dies erhalten und wenn Sie die foobar-Tabelle überprüfen, wird die id-Spalte automatisch um 1 erhöht und id ist ein Primärschlüssel:

1    one
2    two
3    three
4
Eric Leschinski

Wenn Sie dies über den Designer tun möchten, folgen Sie den Anweisungen hier "Änderungen speichern ist nicht zulässig", wenn Sie eine vorhandene Spalte so ändern, dass sie nullwertfähig ist

3
Daveo

Ja, du kannst. Gehen Sie zu Tools> Designers> Table and Designers und deaktivieren Sie das Kontrollkästchen "Speichern von Änderungen, die die Tabellenwiederherstellung verhindern".

2
Peter Pauletto

Wenn Sie keine neue Spalte hinzufügen möchten und sicherstellen können, dass Ihre aktuelle int-Spalte eindeutig ist, können Sie alle Daten in einer temporären Tabelle auswählen, die Tabelle löschen und die angegebene IDENTITY-Spalte erneut erstellen. Mit SET IDENTITY INSERT ON können Sie dann alle Ihre Daten in der temporären Tabelle in die neue Tabelle einfügen.

2
Duncan Howe

Nein, Sie können einer vorhandenen Spalte mit Daten keine automatische Inkrementierungsoption hinzufügen.

Schauen Sie hier .

1
Homam

Das folgende Skript kann eine gute Lösung sein. Auch in großen Daten gearbeitet.

ALTER DATABASE WMlive SET RECOVERY SIMPLE WITH NO_WAIT

ALTER TABLE WMBOMTABLE DROP CONSTRAINT PK_WMBomTable

ALTER TABLE WMBOMTABLE Drop-Spalte BOMID

ALTER TABLE WMBOMTABLE ADD BomID int IDENTITY (1, 1) NICHT NULL;

ALTER TABLE WMBOMTABLE ADD CONSTRAINT PK_WMBomTable PRIMARY KEY CLUSTERED (BomID);

ALTER DATABASE WMlive SET RECOVERY FULL WITH NO_WAIT

0
Jatin Dave