Hinzufügen einer Identität zu einer vorhandenen Spalte

445

Ich muss den Primärschlüssel einer Tabelle in eine Identitätsspalte ändern, und die Tabelle enthält bereits mehrere Zeilen.

Ich habe ein Skript zum Bereinigen der IDs, um sicherzustellen, dass sie ab 1 sequentiell sind. Funktioniert in meiner Testdatenbank einwandfrei.

Was ist der SQL-Befehl, um die Spalte so zu ändern, dass sie eine Identitätseigenschaft hat?

Kirschstein
quelle

Antworten:

482

Sie können die vorhandenen Spalten für die Identität nicht ändern.

Sie haben 2 Möglichkeiten,

  1. Erstellen Sie eine neue Tabelle mit Identität und löschen Sie die vorhandene Tabelle

  2. Erstellen Sie eine neue Spalte mit Identität und löschen Sie die vorhandene Spalte

Vorgehensweise 1. ( Neue Tabelle ) Hier können Sie die vorhandenen Datenwerte in der neu erstellten Identitätsspalte beibehalten.

CREATE TABLE dbo.Tmp_Names
    (
      Id int NOT NULL
             IDENTITY(1, 1),
      Name varchar(50) NULL
    )
ON  [PRIMARY]
go

SET IDENTITY_INSERT dbo.Tmp_Names ON
go

IF EXISTS ( SELECT  *
            FROM    dbo.Names ) 
    INSERT  INTO dbo.Tmp_Names ( Id, Name )
            SELECT  Id,
                    Name
            FROM    dbo.Names TABLOCKX
go

SET IDENTITY_INSERT dbo.Tmp_Names OFF
go

DROP TABLE dbo.Names
go

Exec sp_rename 'Tmp_Names', 'Names'

Ansatz 2 ( Neue Spalte ) Sie können die vorhandenen Datenwerte in der neu erstellten Identitätsspalte nicht beibehalten. Die Identitätsspalte enthält die Zahlenfolge.

Alter Table Names
Add Id_new Int Identity(1, 1)
Go

Alter Table Names Drop Column ID
Go

Exec sp_rename 'Names.Id_new', 'ID', 'Column'

Weitere Informationen finden Sie im folgenden Beitrag zum Microsoft SQL Server-Forum:

So ändern Sie die Spalte in Identität (1,1)

John Sansom
quelle
49
Wenn die Tabellendaten klein sind, funktioniert diese Option gret. Wenn die Tabelle groß ist, gibt es eine andere Option, die ich bevorzuge: Verwenden Sie ALTER TABLE ... SWITCH, um das Tabellenschema durch eine andere Version mit einer IDENTITY-Spalte, aber ansonsten einem identischen Schema zu ersetzen. Der Vorteil des ALTER TABLE .... SWITCH-Ansatzes besteht darin, dass er schnell abgeschlossen wird (unter 5 Sekunden für eine Tabelle mit Milliarden Zeilen), da keine Tabellendaten kopiert oder geändert werden müssen. Es gibt jedoch Vorbehalte und Einschränkungen. Siehe meine Antwort unten für Details.
Justin Grant
7
@ Justin Grat: Eine sehr interessante Alternative und eine, die ich nicht in Betracht gezogen hatte! Der Grund dafür ist, dass IDENTITY eine Spalteneigenschaft und kein Datentyp ist. Daher überprüft die SWITCH-Methode die Schemas zwischen den beiden Tabellen (alt und neu) unabhängig vom IDENTITY-Unterschied als identifizierbar. Danke für das Teilen!
John Sansom
Wenn Sie nicht viele Daten haben, kann das "Erstellen der Tabelle" durch Generieren eines Skripts aus SSMS erreicht werden. Klicken Sie mit der rechten Maustaste auf die Tabelle> Tabelle scripsen als> TABELLE erstellen an> (neuer Abfrageeditor?). IDENTITY(1, 1)
Lassen
Man kann auch SSMS verwenden, um dies durchzusetzen. Gehen Sie zu Extras> Optionen> Designer> Deaktivieren Sie "Speichern von Änderungen verhindern, die eine Neuerstellung der Tabelle erfordern". Übrigens wird dies für ziemlich große Tabellen nicht empfohlen.
Zafar
In PostgreSQL können Sie einer vorhandenen Ganzzahlspalte mit dem folgenden Befehl eine Identität hinzufügen: alter table {table_name} alter column {column_name} add wird immer als Identität generiert (Neustart mit {number});
Andrew Mackie
208

In SQL 2005 und höher gibt es einen Trick, um dieses Problem zu lösen, ohne die Datenseiten der Tabelle zu ändern. Dies ist wichtig für große Tabellen, bei denen das Berühren jeder Datenseite Minuten oder Stunden dauern kann. Der Trick funktioniert auch dann, wenn die Identitätsspalte ein Primärschlüssel ist, Teil eines gruppierten oder nicht gruppierten Index oder anderer Fallstricke ist, die die einfachere Lösung "Spalte hinzufügen / entfernen / umbenennen" auslösen können.

Hier ist der Trick: Mit der Anweisung ALTER TABLE ... SWITCH von SQL Server können Sie das Schema einer Tabelle ändern, ohne die Daten zu ändern. Dies bedeutet, dass Sie eine Tabelle durch eine IDENTITY durch ein identisches Tabellenschema, jedoch ohne eine IDENTITY-Spalte ersetzen können. Der gleiche Trick funktioniert, um einer vorhandenen Spalte IDENTITY hinzuzufügen.

Normalerweise wird ALTER TABLE ... SWITCH verwendet, um eine vollständige Partition in einer partitionierten Tabelle effizient durch eine neue, leere Partition zu ersetzen. Es kann aber auch in nicht partitionierten Tabellen verwendet werden.

Ich habe diesen Trick verwendet, um in weniger als 5 Sekunden eine Spalte einer 2,5-Milliarden-Zeilentabelle von IDENTITY in eine Nicht-IDENTITY zu konvertieren (um eine mehrstündige Abfrage auszuführen, deren Abfrageplan für Nicht-IDENTITY besser funktioniert Spalten) und stellte dann die IDENTITY-Einstellung in weniger als 5 Sekunden wieder her.

Hier ist ein Codebeispiel, wie es funktioniert.

 CREATE TABLE Test
 (
   id int identity(1,1),
   somecolumn varchar(10)
 );

 INSERT INTO Test VALUES ('Hello');
 INSERT INTO Test VALUES ('World');

 -- copy the table. use same schema, but no identity
 CREATE TABLE Test2
 (
   id int NOT NULL,
   somecolumn varchar(10)
 );

 ALTER TABLE Test SWITCH TO Test2;

 -- drop the original (now empty) table
 DROP TABLE Test;

 -- rename new table to old table's name
 EXEC sp_rename 'Test2','Test';

 -- update the identity seed
 DBCC CHECKIDENT('Test');

 -- see same records
 SELECT * FROM Test; 

Dies ist offensichtlich aufwändiger als die Lösungen in anderen Antworten, aber wenn Ihr Tisch groß ist, kann dies ein echter Lebensretter sein. Es gibt einige Einschränkungen:

  • Soweit ich weiß, können Sie mit dieser Methode nur die Identität der Spalten Ihrer Tabelle ändern. Das Hinzufügen / Entfernen von Spalten, das Ändern der Nullfähigkeit usw. ist nicht zulässig.
  • Sie müssen vor dem Umschalten die Foriegn-Schlüssel ablegen und danach wiederherstellen.
  • Gleiches gilt für WITH SCHEMABINDING-Funktionen, Ansichten usw.
  • Die Indizes der neuen Tabelle müssen genau übereinstimmen (gleiche Spalten, gleiche Reihenfolge usw.)
  • Alte und neue Tabellen müssen sich in derselben Dateigruppe befinden.
  • Funktioniert nur unter SQL Server 2005 oder höher
  • Ich habe vorher geglaubt, dass dieser Trick nur in den Enterprise- oder Developer-Editionen von SQL Server funktioniert (da Partitionen nur in Enterprise- und Developer-Versionen unterstützt werden), aber Mason G. Zhwiti sagt in seinem Kommentar unten, dass er auch in SQL Standard Edition funktioniert. Ich gehe davon aus, dass dies bedeutet, dass die Einschränkung auf Enterprise oder Developer nicht für ALTER TABLE ... SWITCH gilt.

Es gibt einen guten Artikel über TechNet, in dem die oben genannten Anforderungen aufgeführt sind.

UPDATE - Eric Wu hatte unten einen Kommentar, der wichtige Informationen zu dieser Lösung hinzufügt. Kopieren Sie es hier, um sicherzustellen, dass es mehr Aufmerksamkeit erhält:

Es gibt hier eine weitere Einschränkung, die erwähnenswert ist. Obwohl die neue Tabelle gerne Daten aus der alten Tabelle empfängt und alle neuen Zeilen nach einem Identitätsmuster eingefügt werden, beginnen sie bei 1 und werden möglicherweise unterbrochen, wenn die Spalte ein Primärschlüssel ist. Ziehen Sie in Betracht, DBCC CHECKIDENT('<newTableName>')sofort nach dem Umschalten zu laufen . Weitere Informationen finden Sie unter msdn.microsoft.com/en-us/library/ms176057.aspx .

Wenn die Tabelle aktiv um neue Zeilen erweitert wird (was bedeutet, dass zwischen dem Hinzufügen von IDENTITY und dem Hinzufügen neuer Zeilen nicht viel Ausfallzeit besteht, möchten DBCC CHECKIDENTSie stattdessen den Identitätsstartwert im neuen Tabellenschema manuell festlegen Größer als die größte vorhandene ID in der Tabelle, z IDENTITY (2435457, 1). B. Sie können möglicherweise sowohl die ALTER TABLE...SWITCHals auch die DBCC CHECKIDENTin eine Transaktion einbeziehen (oder nicht - haben dies nicht getestet), aber das manuelle Festlegen des Startwerts scheint einfacher und sicherer zu sein.

Wenn der Tabelle keine neuen Zeilen hinzugefügt werden (oder sie werden nur gelegentlich hinzugefügt, wie bei einem täglichen ETL-Prozess), tritt diese Race-Bedingung natürlich nicht auf, daher DBCC CHECKIDENTist dies in Ordnung.

Justin Grant
quelle
5
Wenn mein Gedächtnis korrekt ist, kam mir die Idee aus diesem Artikel: sqlservercentral.com/articles/T-SQL/61979
Justin Grant
2
Zu Ihrer Information, dies scheint auch auf der Standardversion von SQL 2008 R2 zu funktionieren. Vielleicht haben sie diese Funktion genauso aktiviert wie jetzt die Möglichkeit, die Sicherungskomprimierung zu aktivieren.
Mason G. Zhwiti
3
@jbatista - Die Frage des OP besagte, dass er bereits einen Primärschlüssel in der Tabelle hatte und bereits die richtigen Werte sicherstellen konnte, aber er wollte ihn einfach in eine IDENTITY-Spalte ändern. Meine obige Antwort konzentriert sich auf diesen engen Anwendungsfall: Wie man die IDENTITÄT zu einer Spalte hinzufügt, ohne tatsächlich Daten zu ändern. Der Ansatz, den ich oben dokumentiere, spart viel Zeit für große Tabellen. Wenn Sie Daten ändern müssen, müssen Sie andere Lösungen verwenden.
Justin Grant
3
Es gibt hier eine weitere Einschränkung, die erwähnenswert ist. Obwohl die neue Tabelle gerne Daten aus der alten Tabelle empfängt und alle neuen Zeilen nach einem Identitätsmuster eingefügt werden, beginnen sie bei 1 und brechen möglicherweise, wenn die Spalte ein Primärschlüssel ist. Ziehen Sie in Betracht, DBCC CHECKIDENT('<newTableName>')sofort nach dem Umschalten zu laufen . Weitere Informationen finden Sie unter msdn.microsoft.com/en-us/library/ms176057.aspx .
Eric Wu
3
Das ist eine großartige Antwort! Beachten Sie auch, dass die Nullfähigkeit von Spalten gleich sein muss. Wenn Sie also die Spaltennullbarkeit ändern müssen, müssen Sie dies zu einem späteren Zeitpunkt tun. Gleiches gilt für PK-Einschränkungen. Ich ändere auch den Identitätswert in der Tabellenerstellung, um dem aktuellen Maximum zu entsprechen: IDENTITÄT (maxID + 1, 1)
Philippe
71

Sie können eine Spalte nicht als IDENTITY-Spalte ändern. Sie müssen lediglich eine neue Spalte erstellen, die von Anfang an als IDENTITÄT definiert ist. Löschen Sie dann die alte Spalte und benennen Sie die neue in den alten Namen um.

ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'

Marc

marc_s
quelle
Entweder ist der Parameter \ @objname nicht eindeutig oder der beanspruchte \ @objtype (COLUMN) ist falsch.
Jenny O'Reilly
1
@ JennyO'Reilly: Stellen Sie das in eine separate Frage und zeigen Sie uns den vollständigen Befehl, den Sie verwenden!
marc_s
2
Es war die sp_rename-Prozedur, die fehlgeschlagen ist. Ich habe eine Lösung für den Stapelüberlauf gefunden, indem ich nach dem Fehlertext gesucht habe. Es scheint eine strenge Syntaxregel in Klammern zu sein, obwohl meine Tabelle keinerlei Sonderzeichen enthält.
Jenny O'Reilly
1
oder es könnte sein wie: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' und 'ALTER TABLE (yourTable) ADD OldColumnName INT IDENTITY (1,1)', warum umbenennen: p
RK Sharma
Marc, ich habe genau diesen Befehl an einer riesigen Tabelle (~ 300 Mio. Zeilen) versucht, aber ich habe den Vorgang nach ~ 10 Minuten gestoppt
Naomi
14

Hier wird eine coole Lösung beschrieben: SQL SERVER - Hinzufügen oder Entfernen der Identitätseigenschaft in der Spalte

Bearbeiten Sie kurz Ihre Tabelle manuell in SQL Manager, wechseln Sie die Identität, SPEICHERN SIE KEINE Änderungen, zeigen Sie einfach das Skript an, das für die Änderungen erstellt wird, kopieren Sie es und verwenden Sie es später.

Dies spart viel Zeit, da es (das Skript) alle Fremdschlüssel, Indizes usw. enthält, die sich auf die von Ihnen geänderte Tabelle beziehen. Manuell schreiben ... Gott bewahre.

Greenoldman
quelle
Dies ist die Lösung, die ich verwendet habe - SSMS generiert das T-SQL, um die Änderung vorzunehmen. Dazu wird eine neue temporäre Tabelle mit demselben Schemadesign erstellt, anschließend alle Zeilen in die Tabelle kopiert, der Ursprung entfernt und umbenannt . Es kann etwas dauern, bis es vollständig ausgeführt ist, aber es hat perfekt funktioniert.
Mdelvecchio
Ich glaube nicht, dass Pinal Dave tatsächlich sagt, dass Sie das von Ihnen generierte Skript ausführen müssen, sondern nur, um zu zeigen, was die Änderung über die Benutzeroberfläche für Sie bewirkt ...
Zack
Diese Skriptfunktion in SSMS (beim Ändern der Definition einer Tabelle) ist tatsächlich die einzig richtige Funktion beim Dokumentieren einer partitionierten Tabelle. Der am besten geeignete Ort 'task' -> 'script table' vergessen Sie immer, die Partitionierungsfunktion zu skripten!
Martijn van der Jagt
1
Kann für jemanden hilfreich sein. Um das Änderungsskript nach Änderungen zu erhalten. Klicken Sie im Entwurfsmodus auf SSMS mit der rechten Maustaste auf die Tabelle, wählen Sie die Option "Änderungsskript generieren" und speichern Sie das Skript auf dem lokalen Laufwerk
Vijai
6

Einfache Erklärung

Benennen Sie die vorhandene Spalte mit sp_RENAME um

EXEC sp_RENAME 'Table_Name.Existing_ColumnName', 'New_ColumnName', 'COLUMN'

Beispiel für Umbenennen:

Die vorhandene Spalte UserID wird in OldUserID umbenannt

EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'

Fügen Sie dann mithilfe der Änderungsabfrage eine neue Spalte hinzu, um sie als Primärschlüssel und Identitätswert festzulegen

ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)

Beispiel für Set Primary Key

Der neu erstellte Spaltenname lautet UserID

ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)

Löschen Sie dann die umbenannte Spalte

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Beispiel für eine umbenannte Drop-Spalte

ALTER TABLE Users DROP COLUMN OldUserID

Jetzt fügen wir der vorhandenen Spalte in der Tabelle einen Primärschlüssel und eine Identität hinzu.

Sathish Chelladurai
quelle
5

Ich bin ein Java-Entwickler, der zufällig in ein Team ohne DBA eingestiegen ist und in dem ich als Entwickler keine DBA-Rechte erhalten kann. Ich wurde beauftragt, ein ganzes Schema zwischen zwei Datenbanken zu verschieben. Ohne DBA musste ich dies tun und Skripte ausführen, da ich die GUI in SQL Server 2008 nicht verwenden konnte, weil ich keine Administratorrechte hatte.

Alles wurde ohne Probleme verschoben. Als ich jedoch eine gespeicherte Prozedur in der neuen schema.table ausführte, stellte ich fest, dass ich das Identitätsfeld in einer Tabelle verloren hatte. Ich habe das Skript, mit dem die Tabelle erstellt wurde, noch einmal überprüft und es war vorhanden. SQL Server hat es jedoch nicht erhalten, als ich das Skript ausgeführt habe. Ein DBA sagte mir später, dass er das gleiche Problem schon einmal gesehen habe.

Für SQL Server 2008 sind dies auf jeden Fall die Schritte, die ich unternommen habe, um dieses Problem zu lösen, und sie haben funktioniert. Daher veröffentliche ich dies hier in der Hoffnung, dass es jemandem helfen wird. Dies habe ich getan, da ich FK-Abhängigkeiten von einer anderen Tabelle hatte, was dies schwieriger machte:

Ich habe diese Abfrage verwendet, um zu überprüfen, ob die Identität tatsächlich fehlt, und um Abhängigkeiten von der Tabelle anzuzeigen.

1.) Statistiken zu einer Tabelle finden:

exec sp_help 'dbo.table_name_old';

2.) Erstellen Sie eine doppelte, identische neue Tabelle, außer fügen Sie ein Identitätsfeld in das PK-Feld ein, in dem es zuvor war.

3.) Deaktivieren Sie die Identität, um Daten zu verschieben.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Übertragen Sie die Daten.

INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT 
field1, field2, etc...
FROM 
dbo.table_name_old;

5.) Überprüfen Sie, ob die Daten vorhanden sind.

SELECT * FROM dbo.table_name_new

6.) Aktivieren Sie die Identität erneut.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Dies ist das beste Skript, das ich gefunden habe, um alle FK-Beziehungen zu erhalten, um zu überprüfen, auf welche Tabelle (n) die ursprüngliche Tabelle als Abhängigkeiten verweist, und ich bin auf viele gestoßen, also ist es ein Bewahrer!

SELECT f.name AS ForeignKey,
   OBJECT_NAME(f.parent_object_id) AS TableName,
   COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
   OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
   COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
   ON f.OBJECT_ID = fc.constraint_object_id
   ORDER BY ReferenceTableName;

8.) Stellen Sie vor diesem nächsten Schritt sicher, dass Sie alle PK- und FK-Skripte für alle beteiligten Tabellen haben.

9.) Sie können mit der rechten Maustaste auf jeden Schlüssel klicken und dieses Skript mit SQL Server 2008 ausführen

10.) Löschen Sie die FKs mit dieser Syntax aus den Abhängigkeitstabellen:

ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]

11.) Legen Sie die Originaltabelle ab:

DROP TABLE dbo.table_name_old;

13.) Diese nächsten Schritte basieren auf den Skripten, die Sie in Schritt 9 in SQL Server 2008 erstellt haben.

- Fügen Sie die PK der neuen Tabelle hinzu.

- Fügen Sie den FK zur neuen Tabelle hinzu.

- Fügen Sie die FKs wieder zur Abhängigkeitstabelle hinzu.

14.) Überprüfen Sie, ob alles korrekt und vollständig ist. Ich habe die GUI verwendet, um die Tabellen anzusehen.

15.) Benennen Sie die neue Tabelle in den ursprünglichen Tabellennamen um.

exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';

Endlich hat alles geklappt!

James Drinkard
quelle
4

Sie können es nicht so machen, Sie müssen eine weitere Spalte hinzufügen, die ursprüngliche Spalte löschen und die neue Spalte umbenennen oder oder eine neue Tabelle erstellen, die Daten kopieren und die alte Tabelle löschen, gefolgt vom Umbenennen der neuen Tabelle in die alte Tabelle

Wenn Sie SSMS verwenden und die Identitätseigenschaft im Designer auf ON setzen, führt SQL Server hinter den Kulissen Folgendes aus. Wenn Sie also eine Tabelle mit dem Namen [Benutzer] haben, geschieht dies, wenn Sie Benutzer-ID und Identität festlegen

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

Trotzdem gibt es eine Möglichkeit, die Systemtabelle zu hacken, um dies durch Setzen des bitweisen Werts zu erreichen, aber das wird nicht unterstützt und ich würde es nicht tun

SQLMenace
quelle
4

Wie ich im Normalfall verstanden habe, erstellen wir eine Tabelle mit einem Primärschlüssel mit der Eigenschaft "Identität".
Das Umbenennen oder Löschen einer Spalte, die der Primärschlüsseleinschränkung zugeordnet ist , ist daher nicht möglich, da die Einschränkungsregeln die Spaltenstruktur validieren.
Um dies zu erreichen, müssen wir einige Schritte folgendermaßen ausführen :
Nehmen wir an, TableName = 'Employee' und ColumnName = 'EmployeeId'

1. Fügen Sie der Tabelle 'Employee' eine neue Spalte 'EmployeeId_new' hinzu.
ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY ( 1,1)

  1. Entfernen Sie nun die Spalte 'EmployeeId' aus der Tabelle 'Employee'.
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Dies führt zu Fehlern, da die Regeln für die Einschränkung des Primärschlüssels anwendbar sind und die Spaltenstruktur überprüft wird.
    * ### 'Nachricht 5074, Ebene 16, Status 1, Zeile 1 Das Objekt [PK_dbo.Employee] ist abhängig von Spalte [EmployeeId].' ###

  3. Daher müssen wir zuerst die Primärschlüsseleinschränkung aus der Tabelle 'Mitarbeiter' entfernen und dann die Spalte
    ALTER TABLE Employee DROP-Einschränkung [PK_dbo.Employee] entfernen.

  4. Jetzt können wir die Spalte 'EmployeeId' aus der Tabelle 'Employee' entfernen, wie im vorherigen Schritt, in dem der Fehler
    ALTER TABLE Employee DROP COLUMN EmployeeId angezeigt wurde

  5. Jetzt wurde die Spalte 'EmployeeId' aus der Tabelle entfernt. Daher werden wir die neu hinzugefügte neue Spalte 'EmployeeId_new' mit 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN' umbenennen.

  6. Um die Tabelle in der gleichen Form wie zuvor neu anzuordnen , müssen wir die Primärschlüsseleinschränkung für die Spalte 'EmployeeId'
    hinzufügen. ALTER TABLE Employee Add Constraint [PK_dbo.Employee] Primärschlüssel (EmployeeId)

8. Jetzt wird die Tabelle 'Employee' mit 'EmployeeId' für Identitätsregeln zusammen mit der vorhandenen Primärschlüsseleinschränkung geändert

Nagendra Upwanshi
quelle
3

Es gibt keine einfache Möglichkeit, die Identitätsfunktion für eine vorhandene Spalte zu aktivieren oder zu deaktivieren. Die einzige saubere Möglichkeit, dies zu tun, besteht darin, eine neue Spalte zu erstellen und sie zu einer Identitätsspalte zu machen oder eine neue Tabelle zu erstellen und Ihre Daten zu migrieren.

Wenn wir SQL Server Management Studio verwenden, um den Identitätswert in der Spalte "id" zu entfernen, wird eine neue temporäre Tabelle erstellt, die Daten werden in die temporäre Tabelle verschoben, die alte Tabelle wird gelöscht und die neue Tabelle wird umbenannt.

Verwenden Sie Management Studio, um die Änderung vorzunehmen, klicken Sie mit der rechten Maustaste in den Designer und wählen Sie "Änderungsskript generieren".

Sie werden sehen, dass SQL Server dies im Hintergrund tut.

Raj
quelle
2

Leider gibt es keinen; Die IDENTITY-Eigenschaft gehört eher zur Tabelle als zur Spalte.

Der einfachere Weg ist es, dies in der GUI zu tun. Wenn dies jedoch keine Option ist, können Sie die Daten weitestgehend kopieren, die Spalte löschen, sie erneut mit Identität hinzufügen und die Daten zurücksetzen.

Sehen Sie hier für ein Blow-by-Blow - Konto.

Jeremy Smyth
quelle
2

Klicken Sie im Objekt-Explorer mit der rechten Maustaste auf den Tabellennamen. Sie erhalten einige Optionen. Klicken Sie auf "Design". Für diese Tabelle wird eine neue Registerkarte geöffnet. Sie können hier unter 'Spalteneigenschaften' eine Identitätsbeschränkung hinzufügen.

vamsi_874
quelle
2

So ändern Sie die Identitätseigenschaften für eine Spalte:

  • Klicken Sie im Server-Explorer mit der rechten Maustaste auf die Tabelle mit den Identitätseigenschaften, die Sie ändern möchten, und klicken Sie auf Tabellendefinition öffnen. Die Tabelle wird im Tabellen-Designer geöffnet.
  • Deaktivieren Sie das Kontrollkästchen Nullen zulassen für die Spalte, die Sie ändern möchten.
  • Erweitern Sie auf der Registerkarte Spalteneigenschaften die Eigenschaft Identitätsspezifikation.
  • Klicken Sie auf die Rasterzelle für die untergeordnete Eigenschaft Is Identity und wählen Sie Ja aus der Dropdown-Liste.
  • Geben Sie einen Wert in die Zelle Identity Seed ein. Dieser Wert wird der ersten Zeile in der Tabelle zugewiesen. Der Wert 1 wird standardmäßig zugewiesen.

Das war's und es hat bei mir funktioniert

Ken.Fukizi
quelle
2

Wenn Sie Visual Studio 2017+ verwenden

  1. Klicken Sie im Server Object Explorer mit der rechten Maustaste auf Ihre Tabelle und wählen Sie "Code anzeigen".
  2. Fügen Sie Ihrer Spalte den Modifikator "IDENTITY" hinzu
  3. Aktualisieren

Dies wird alles für Sie tun.

jdisla
quelle
Ja! Vielen Dank, dass Sie dies vorgeschlagen haben! Ich habe keine SSMS-Version auf meiner Windows 7-Box, mit der ich Designänderungen an Tabellen auf meinem Produktionsserver vornehmen kann, da es 2017 ist, mein SSMS 2014 ist und 2017 SSMS Windows 10 benötigt. Sie haben meinen Tag gemacht. Ging in VS 2017> Server Explorer> stellte eine neue Verbindung zu SQL Server her> klickte mit der rechten Maustaste auf Tabelle> "Tabellendefinition öffnen"> Wala!
JustJohn
Eigentlich habe ich festgestellt, dass Sie mit der rechten Maustaste auf das Feld klicken und Eigenschaften auswählen und dort die Identität
festlegen können,
1

Wenn das ursprüngliche Poster tatsächlich eine vorhandene Spalte als a PRIMARY KEYfür die Tabelle festlegen wollte und die Spalte eigentlich keine IDENTITYSpalte sein musste (zwei verschiedene Dinge), kann dies über t-SQL erfolgen mit:

ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])

Beachten Sie die Klammer um den Spaltennamen nach der PRIMARY KEYOption.

Obwohl dieser Beitrag alt ist und ich davon ausgehe, dass die Anforderer ihn benötigen, waren diese zusätzlichen Informationen für Benutzer, die auf diesen Thread stoßen, hilfreich, da ich der Meinung bin, dass die Konversation zu der Annahme führen könnte, dass eine vorhandene Spalte nicht als a festgelegt werden kann Primärschlüssel, ohne ihn zuerst als neue Spalte hinzuzufügen, was falsch wäre.

A. Omalley
quelle
1

Nach meinem derzeitigen Zustand verfolge ich diesen Ansatz. Ich möchte einer Primärtabelle nach dem Einfügen von Daten per Skript eine Identität geben.

Da ich die Identität anhängen möchte, beginnt sie immer von 1 bis zum Ende der Datensatzanzahl, die ich möchte.

--first drop column and add with identity
ALTER TABLE dbo.tblProductPriceList drop column ID 
ALTER TABLE dbo.tblProductPriceList add ID INT IDENTITY(1,1)

--then add primary key to that column (exist option you can ignore)
IF  NOT EXISTS (SELECT * FROM sys.key_constraints  WHERE object_id = OBJECT_ID(N'[dbo].[PK_tblProductPriceList]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblProductPriceList]'))
    ALTER TABLE [tblProductPriceList] ADD PRIMARY KEY (id)
GO

Dadurch wird dieselbe Primärschlüsselspalte mit Identität erstellt

Ich habe diese Links verwendet: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Primärschlüssel zur vorhandenen Tabelle hinzufügen

Ajay2707
quelle
0

Ich glaube nicht, dass Sie eine vorhandene Spalte mit tsql in eine Identitätsspalte ändern können. Sie können dies jedoch über die Enterprise Manager-Entwurfsansicht tun.

Alternativ können Sie eine neue Zeile als Identitätsspalte erstellen, die alte Spalte löschen und dann Ihre neue Spalte umbenennen.

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED
William Edmondson
quelle
2
Denken Sie daran, dass Sie, wenn Sie dies über SSMS / Enterprise Manager tun, eine neue Tabelle erstellen, Daten kopieren, die alte Tabelle löschen und die neue umbenennen. Das kann ziemlich teuer sein, wenn Sie große Tische haben ...
Scott Ivey
0

Grundsätzlich gibt es vier logische Schritte.

  1. Erstellen Sie eine neue Identitätsspalte. Aktivieren Sie Identität für diese neue Spalte einfügen.

  2. Fügen Sie die Daten aus der Quellenspalte (der Spalte, die Sie in Identität konvertieren möchten) in diese neue Spalte ein.

  3. Deaktivieren Sie die Option Identität für die neue Spalte einfügen.

  4. Löschen Sie Ihre Quellenspalte und benennen Sie die neue Spalte in den Namen der Quellenspalte um.

Es kann einige komplexere Situationen geben, z. B. das Arbeiten auf mehreren Servern usw.

Weitere Informationen zu den Schritten finden Sie im folgenden Artikel (mit ssms & T-sql). Diese Schritte sind für Anfänger gedacht, die weniger Erfahrung mit T-SQL haben.

http://social.technet.microsoft.com/wiki/contents/articles/23816.how-to-convert-int-column-to-identity-in-the-ms-sql-server.aspx

Shivalik Chakravarty
quelle
0

generiert ein Skript für alle Tabellen mit Primärschlüssel = bigint, für die kein Identitätssatz festgelegt ist; Dadurch wird eine Liste der generierten Skripte für jede Tabelle zurückgegeben.

SET NOCOUNT ON;

declare @sql table(s varchar(max), id int identity)

DECLARE @table_name nvarchar(max),
        @table_schema nvarchar(max);

DECLARE vendor_cursor CURSOR FOR 
SELECT
  t.name, s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
  ON s.[schema_id] = t.[schema_id]
WHERE EXISTS (
    SELECT
    [c].[name]
    from sys.columns [c]
    join sys.types [y] on [y].system_type_id = [c].system_type_id
    where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
) and NOT EXISTS 
(
  SELECT 1 FROM sys.identity_columns
    WHERE [object_id] = t.[object_id]
) and exists (
    select 1 from sys.indexes as [i] 
    inner join sys.index_columns as [ic]  ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
    where object_name([ic].[object_id]) = [t].[name]
)
OPEN vendor_cursor

FETCH NEXT FROM vendor_cursor 
INTO @table_name, @table_schema

WHILE @@FETCH_STATUS = 0
BEGIN

DELETE FROM @sql

declare @pkname varchar(100),
    @pkcol nvarchar(100)

SELECT  top 1
        @pkname = i.name,
        @pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
FROM    sys.indexes AS [i]
INNER JOIN sys.index_columns AS [ic] ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE   i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name

declare @q nvarchar(max) = 'SELECT  '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'

DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT

insert into  @sql(s) values ('BEGIN TRANSACTION')
insert into  @sql(s) values ('BEGIN TRY')

-- create statement
insert into  @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')

-- column list
insert into @sql(s) 
select 
    '  ['+[c].[name]+'] ' +
    y.name + 

    (case when [y].[name] like '%varchar' then
    coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
    else '' end)

     + ' ' +
    case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
    ( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' + 
    coalesce('DEFAULT ('+(
        REPLACE(
            REPLACE(
                LTrim(
                    RTrim(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        LTrim(
                                            RTrim(
                                                REPLACE(
                                                    REPLACE(
                                                        object_definition([c].default_object_id)
                                                    ,' ','~')
                                                ,')',' ')
                                            )
                                        )
                                    ,' ','*')
                                ,'~',' ')
                            ,' ','~')
                        ,'(',' ')
                    )
                )
            ,' ','*')
        ,'~',' ')
    ) +
    case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
    +
    ')','') + ','
 from sys.columns c
 JOIN sys.types y ON y.system_type_id = c.system_type_id
  where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
 order by [c].column_id


 update @sql set s=left(s,len(s)-1) where id=@@identity

-- closing bracket
insert into @sql(s) values( ')' )

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')

declare @cols nvarchar(max)
SELECT @cols = STUFF(
    (
        select ',['+c.name+']'
        from sys.columns c
        JOIN sys.types y ON y.system_type_id = c.system_type_id
        where c.[object_id] = OBJECT_ID(@table_name)
        and [y].name != 'sysname'
        and [y].name != 'timestamp'
        order by [c].column_id
        FOR XML PATH ('')
     )
    , 1, 1, '')

insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')


insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')

insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')

if ( @pkname is not null ) begin
    insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
    insert into @sql(s)
        select '  ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
        where constraint_name = @pkname
        GROUP BY COLUMN_NAME, ordinal_position
        order by ordinal_position

    -- remove trailing comma
    update @sql set s=left(s,len(s)-1) where id=@@identity
    insert into @sql(s) values ('  )')
end

insert into  @sql(s) values ('--Run your Statements')
insert into  @sql(s) values ('COMMIT TRANSACTION')
insert into  @sql(s) values ('END TRY')
insert into  @sql(s) values ('BEGIN CATCH')
insert into  @sql(s) values ('        ROLLBACK TRANSACTION')
insert into  @sql(s) values ('        DECLARE @Msg NVARCHAR(MAX)  ')
insert into  @sql(s) values ('        SELECT @Msg=ERROR_MESSAGE() ')
insert into  @sql(s) values ('        RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
insert into  @sql(s) values ('END CATCH')

declare @fqry nvarchar(max)

-- result!
SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))


SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
PRINT 'Table: '+@table_name
EXEC sp_executeSql @fqry

    FETCH NEXT FROM vendor_cursor 
    INTO @table_name, @table_schema
END 
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;
Kyle Gibbar
quelle