it-swarm.com.de

Entfernen Sie Identität aus einer Spalte in einer Tabelle

Wir haben eine 5-GB-Tabelle (fast 500 Millionen Zeilen) und möchten die Identitätseigenschaft in einer Spalte entfernen. Wenn wir dies jedoch über SSMS versuchen, kommt es zu einer Zeitüberschreitung.

Kann dies über T-SQL erfolgen?

91
Conrad Jagger

Sie können eine einmal festgelegte IDENTITY-Spezifikation nicht entfernen.

So entfernen Sie die gesamte Spalte:

ALTER TABLE yourTable
DROP COLUMN yourCOlumn;

Informationen zu ALTER TABLE hier

Wenn Sie die Daten beibehalten und die Spalte IDENTITY entfernen müssen, müssen Sie Folgendes tun:

  • Erstellen Sie eine neue Spalte
  • Übertragen Sie die Daten aus der vorhandenen IDENTITY-Spalte in die neue Spalte
  • Löschen Sie die vorhandene IDENTITY-Spalte.
  • Benennen Sie die neue Spalte in den ursprünglichen Spaltennamen um
112
Adam Wenger

Wenn Sie dies tun möchten ohne eine neue Spalte hinzuzufügen und aufzufüllen ,, ohne die Spalten neu anzuordnen und fast ohne Ausfallzeiten weil sich keine Daten auf der Tabelle ändern, lassen Sie uns etwas Magie damit anfangen Partitionierungsfunktion (da jedoch keine Partitionen verwendet werden, ist keine Enterprise Edition erforderlich):

  1. Entfernen Sie alle Fremdschlüssel, die auf diese Tabelle verweisen
  2. Die zu erstellende Tabelle schreiben; alles umbenennen, z. 'MyTable2', 'MyIndex2' usw. Entfernen Sie die IDENTITY-Spezifikation.
  3. Sie sollten jetzt zwei "identische" -ish-Tabellen haben, eine voll und die andere leer ohne IDENTITY.
  4. ALTER TABLE [Original] SWITCH TO [Original2] ausführen
  5. Jetzt ist Ihre ursprüngliche Tabelle leer und die neue Tabelle enthält die Daten. Sie haben die Metadaten für die beiden Tabellen (sofort) gewechselt. 
  6. Löschen Sie die ursprüngliche (jetzt leere Tabelle) exec sys.sp_rename, um die verschiedenen Schemaobjekte wieder in die ursprünglichen Namen umzubenennen. Anschließend können Sie Ihre Fremdschlüssel neu erstellen.

Zum Beispiel gegeben:

CREATE TABLE Original
(
  Id INT IDENTITY PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value ON Original (Value);

INSERT INTO Original
SELECT 'abcd'
UNION ALL 
SELECT 'defg';

Sie können Folgendes tun:

--create new table with no IDENTITY
CREATE TABLE Original2
(
  Id INT PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value2 ON Original2 (Value);

--data before switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

ALTER TABLE Original SWITCH TO Original2;

--data after switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

--clean up
DROP TABLE Original;
EXEC sys.sp_rename 'Original2.IX_Original_Value2', 'IX_Original_Value', 'INDEX';
EXEC sys.sp_rename 'Original2', 'Original', 'OBJECT';


UPDATE Original
SET Id = Id + 1;

SELECT *
FROM Original;
63
Mark Sowul

Dies wird mit Fremd- und Primärschlüsseleinschränkungen unübersichtlich, daher finden Sie hier einige Skripts, die Ihnen auf Ihrem Weg helfen:

Erstellen Sie zuerst eine doppelte Spalte mit einem temporären Namen:

alter table yourTable add tempId int NOT NULL default -1;
update yourTable set tempId = id;

Rufen Sie als Nächstes den Namen Ihrer Primärschlüsseleinschränkung ab:

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable';

Versuchen Sie nun, die Primärschlüsseleinschränkung für Ihre Spalte zu löschen:

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;

Wenn Sie Fremdschlüssel haben, schlägt dies fehl, wenn Sie die Fremdschlüsseleinschränkungen löschen. BEHALTEN SIE, WENN SIE DIESES FÜR SO LAUFEN KÖNNEN, KÖNNEN SIE DIE BESCHRÄNKUNGEN WIEDER SPÄTER HINZUFÜGEN !!!

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable';
alter table otherTable drop constraint fk_otherTable_yourTable;
commit;
..

Nachdem alle Fremdschlüsseleinschränkungen entfernt wurden, können Sie die PK-Einschränkung entfernen, die Spalte löschen, Ihre temporäre Spalte umbenennen und die PK-Einschränkung dieser Spalte hinzufügen:

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;
alter table yourTable drop column id;
EXEC sp_rename 'yourTable.tempId', 'id', 'COLUMN';
ALTER TABLE yourTable ADD CONSTRAINT PK_yourTable_id PRIMARY KEY (id) 
commit;

Fügen Sie schließlich die FK-Einschränkungen wieder hinzu:

alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id);
..

El Fin!

56
Briguy37

Ich hatte gerade das gleiche Problem. 4 Anweisungen in SSMS anstelle der GUI und es war sehr schnell.

  • Machen Sie eine neue Spalte

    alter table users add newusernum int;

  • Werte kopieren

    update users set newusernum=usernum;

  • Lass die alte Spalte fallen

    alter table users drop column usernum;

  • Benennen Sie die neue Spalte in den alten Spaltennamen um

    EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';

15
liberty_

Das folgende Skript entfernt das Identitätsfeld für eine Spalte mit dem Namen 'Id'.

Ich hoffe es hilft.

BEGIN TRAN
BEGIN TRY
    EXEC sp_rename '[SomeTable].[Id]', 'OldId';

    ALTER TABLE [SomeTable] ADD Id int NULL

    EXEC ('UPDATE [SomeTable] SET Id = OldId')

    ALTER TABLE [SomeTable] NOCHECK CONSTRAINT ALL

    ALTER TABLE [SomeTable] DROP CONSTRAINT [PK_constraintName];
    ALTER TABLE [SomeTable] DROP COLUMN OldId
    ALTER TABLE [SomeTable] ALTER COLUMN [Id] INTEGER NOT NULL
    ALTER TABLE [SomeTable] ADD CONSTRAINT PK_JobInfo PRIMARY KEY (Id)

    ALTER TABLE [SomeTable] CHECK CONSTRAINT ALL

    COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN   
    SELECT ERROR_MESSAGE ()
END CATCH
9
bluedot

Der unten beschriebene Code funktioniert gut, wenn wir den Namen der Identitätsspalte nicht kennen.

und möchte Daten in eine neue temporäre Tabelle wie Invoice_DELETED kopieren. und das nächste Mal, wenn wir verwenden: Einfügen in Invoice_DELETED Wählen Sie * aus der Rechnung aus, wo ...

SELECT t1.*
INTO Invoice_DELETED
FROM Invoice t1
LEFT JOIN Invoice ON 1 = 0
--WHERE t1.InvoiceID = @InvoiceID

besonderer Dank geht an 'Andriy M'

weitere Informationen finden Sie unter: https://dba.stackexchange.com/a/138345/101038

3
Zolfaghari
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'

Der obige Code funktioniert jedoch nur, wenn keine Primär-Fremdschlüssel-Beziehung besteht

1
Jekin Kalariya

Ich hatte die gleiche Anforderung, und Sie könnten es auf diese Weise versuchen, die ich Ihnen persönlich empfehle. Bitte entwerfen Sie Ihre Tabelle manuell und generieren Sie das Skript. Was ich unten gemacht habe, war, den alten Tabellennamen umzubenennen und auch das Backup zu machen.

==============================

            /* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
            BEGIN TRANSACTION

            SET QUOTED_IDENTIFIER ON
            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
            ALTER TABLE dbo.SI_Provider_Profile
                DROP CONSTRAINT DF_SI_Provider_Profile_SIdtDateTimeStamp
            GO
            ALTER TABLE dbo.SI_Provider_Profile
                DROP CONSTRAINT DF_SI_Provider_Profile_SIbHotelPreLoaded
            GO
            CREATE TABLE dbo.Tmp_SI_Provider_Profile
                (
                SI_lProvider_Profile_ID int NOT NULL,
                SI_lSerko_Integrator_Token_ID int NOT NULL,
                SI_sSerko_Integrator_Provider varchar(50) NOT NULL,
                SI_sSerko_Integrator_Profile varchar(50) NOT NULL,
                SI_dtDate_Time_Stamp datetime NOT NULL,
                SI_lProvider_ID int NULL,
                SI_sDisplay_Name varchar(10) NULL,
                SI_lPurchased_From int NULL,
                SI_sProvider_UniqueID varchar(255) NULL,
                SI_bHotel_Pre_Loaded bit NOT NULL,
                SI_sSiteName varchar(255) NULL
                )  ON [PRIMARY]
            GO
            ALTER TABLE dbo.Tmp_SI_Provider_Profile SET (LOCK_ESCALATION = TABLE)
            GO
            ALTER TABLE dbo.Tmp_SI_Provider_Profile ADD CONSTRAINT
                DF_SI_Provider_Profile_SIdtDateTimeStamp DEFAULT (getdate()) FOR SI_dtDate_Time_Stamp
            GO
            ALTER TABLE dbo.Tmp_SI_Provider_Profile ADD CONSTRAINT
                DF_SI_Provider_Profile_SIbHotelPreLoaded DEFAULT ((0)) FOR SI_bHotel_Pre_Loaded
            GO
            IF EXISTS(SELECT * FROM dbo.SI_Provider_Profile)
                 EXEC('INSERT INTO dbo.Tmp_SI_Provider_Profile (SI_lProvider_Profile_ID, SI_lSerko_Integrator_Token_ID, SI_sSerko_Integrator_Provider, SI_sSerko_Integrator_Profile, SI_dtDate_Time_Stamp, SI_lProvider_ID, SI_sDisplay_Name, SI_lPurchased_From, SI_sProvider_UniqueID, SI_bHotel_Pre_Loaded, SI_sSiteName)
                    SELECT SI_lProvider_Profile_ID, SI_lSerko_Integrator_Token_ID, SI_sSerko_Integrator_Provider, SI_sSerko_Integrator_Profile, SI_dtDate_Time_Stamp, SI_lProvider_ID, SI_sDisplay_Name, SI_lPurchased_From, SI_sProvider_UniqueID, SI_bHotel_Pre_Loaded, SI_sSiteName FROM dbo.SI_Provider_Profile WITH (HOLDLOCK TABLOCKX)')
            GO

            -- Rename the primary key constraint or unique key In SQL Server constraints such as primary keys or foreign keys are objects in their own right, even though they are dependent upon the "containing" table.
            EXEC sp_rename 'dbo.SI_Provider_Profile.PK_SI_Provider_Profile', 'PK_SI_Provider_Profile_Old';
            GO
            -- backup old table in case of 
            EXECUTE sp_rename N'dbo.SI_Provider_Profile', N'SI_Provider_Profile_Old', 'OBJECT'
            GO

            EXECUTE sp_rename N'dbo.Tmp_SI_Provider_Profile', N'SI_Provider_Profile', 'OBJECT'
            GO

            ALTER TABLE dbo.SI_Provider_Profile ADD CONSTRAINT
                PK_SI_Provider_Profile PRIMARY KEY NONCLUSTERED 
                (
                SI_lProvider_Profile_ID
                ) WITH( PAD_INDEX = OFF, FILLFACTOR = 90, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

            GO
            COMMIT TRANSACTION

==============================

0
Cena Jang

Nur für jemanden, der das gleiche Problem hatte, habe ich ... Wenn Sie nur einmal etwas einfügen wollen, können Sie so etwas tun.

Nehmen wir an, Sie haben eine Tabelle mit zwei Spalten

ID Identity (1,1) | Name Varchar

und Sie möchten eine Zeile mit der ID = 4 einfügen. Sie haben es also auf 3 gesetzt, so dass die nächste 4 ist

DBCC CHECKIDENT([YourTable], RESEED, 3)

Machen Sie den Insert

INSERT  INTO [YourTable]
        ( Name )
VALUES  ( 'Client' )

Und bringen Sie Ihren Samen auf die höchste ID zurück, nehmen wir an, 15 ist

DBCC CHECKIDENT([YourTable], RESEED, 15)

Erledigt!

0
Faruk Feres