Tenemos una tabla de 5 GB (casi 500 millones de filas) y queremos eliminar la propiedad de identidad en una de las columnas, pero cuando intentamos hacer esto a través de SSMS, se agota el tiempo de espera.
¿Se puede hacer esto a través de T-SQL?
Tenemos una tabla de 5 GB (casi 500 millones de filas) y queremos eliminar la propiedad de identidad en una de las columnas, pero cuando intentamos hacer esto a través de SSMS, se agota el tiempo de espera.
¿Se puede hacer esto a través de T-SQL?
Respuestas:
No puede eliminar una IDENTITY
especificación una vez establecida.
Para eliminar toda la columna:
ALTER TABLE yourTable
DROP COLUMN yourCOlumn;
Información sobre ALTER TABLE aquí
Si necesita conservar los datos, pero eliminar la IDENTITY
columna, deberá:
IDENTITY
columna existente a la nueva columnaIDENTITY
columna existente .identity
columna se usa como parte de una foreign key
en otra tabla, primero tendrá que eliminar las restricciones, luego tomar medidas como @AdamWenger mencionó sobre la eliminación de la identidad attribute/property
... También puede consultar este enlace para obtener más detalles sobre eliminar solo el atributo: blog.sqlauthority.com/2009/05/03/… .. ¡Buena suerte!
Si desea hacer esto sin agregar y completar una nueva columna , sin reordenar las columnas y casi sin tiempo de inactividad porque no hay datos cambiando en la tabla, hagamos un poco de magia con la funcionalidad de particionamiento (pero como no se utilizan particiones, no debe hacerlo) no necesita edición Enterprise):
ALTER TABLE [Original] SWITCH TO [Original2]
exec sys.sp_rename
para cambiar el nombre de los diversos objetos de esquema a los nombres originales, y luego puede recrear sus claves foráneas.Por ejemplo, dado:
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';
Puedes hacer lo siguiente:
--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
IF NOT EXISTS (SELECT * FROM Original) 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;
Esto se complica con las restricciones de clave principal y externa, así que aquí hay algunos scripts para ayudarlo en su camino:
Primero, cree una columna duplicada con un nombre temporal:
alter table yourTable add tempId int NOT NULL default -1;
update yourTable set tempId = id;
A continuación, obtenga el nombre de su restricción de clave principal:
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable';
Ahora intente eliminar la restricción de clave principal para su columna:
ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;
Si tiene claves foráneas, fallará, por lo que, si es así, elimine las restricciones de claves foráneas. ¡MANTENGA LA PISTA DE LAS TABLAS PARA LAS QUE FUNCIONA ESTO PARA QUE PUEDE AGREGAR LAS RESTRICCIONES MÁS TARDE!
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable';
alter table otherTable drop constraint fk_otherTable_yourTable;
commit;
..
Una vez que se hayan eliminado todas las restricciones de clave externa, podrá eliminar la restricción PK, soltar esa columna, cambiar el nombre de su columna temporal y agregar la restricción PK a esa columna:
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;
Finalmente, agregue las restricciones FK nuevamente en:
alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id);
..
El Fin!
Select t.name 'Table', i.name 'Index', c.name 'Column', i.is_primary_key, i.is_unique From sys.tables t Inner Join sys.indexes i On i.object_id = t.object_id Inner Join sys.index_columns ic ON ic.object_id = i.object_id And i.index_id = ic.index_id Inner Join sys.columns c ON ic.object_id = c.object_id and ic.column_id = c.column_id Where t.name = 'tableName' Order By t.name, i.name, i.index_id, ic.index_column_id
Acabo de tener este mismo problema. 4 declaraciones en SSMS en lugar de usar la GUI y fue muy rápido.
Hacer una nueva columna
alter table users add newusernum int;
Copiar valores sobre
update users set newusernum=usernum;
Suelta la columna vieja
alter table users drop column usernum;
Cambie el nombre de la nueva columna al nombre de la columna anterior
EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';
El siguiente script elimina el campo de identidad para una columna llamada 'Id'
Espero eso ayude.
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
El siguiente código funciona bien cuando no conocemos el nombre de la columna de identidad .
Necesita copiar datos en una nueva tabla temporal como Invoice_DELETED
. y la próxima vez que usemos:
insert into Invoice_DELETED select * from Invoice where ...
SELECT t1.*
INTO Invoice_DELETED
FROM Invoice t1
LEFT JOIN Invoice ON 1 = 0
--WHERE t1.InvoiceID = @InvoiceID
Para obtener más explicaciones, consulte: https://dba.stackexchange.com/a/138345/101038
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
Sin embargo, el código anterior solo funciona si no hay una relación de clave primaria-externa
Solo para alguien que tiene el mismo problema que yo. Si solo desea hacer una inserción solo una vez, puede hacer algo como esto.
Supongamos que tiene una tabla con dos columnas.
ID Identity (1,1) | Name Varchar
y desea insertar una fila con el ID = 4. Entonces, vuelva a colocarla en 3 para que la siguiente sea 4
DBCC CHECKIDENT([YourTable], RESEED, 3)
Hacer el inserto
INSERT INTO [YourTable]
( Name )
VALUES ( 'Client' )
Y devuelva su semilla a la ID más alta, supongamos que es 15
DBCC CHECKIDENT([YourTable], RESEED, 15)
¡Hecho!
Tenía el mismo requisito, y podría intentarlo de esta manera, que personalmente le recomiendo, diseñe manualmente su tabla y genere el script, y lo que hice a continuación fue cambiar el nombre de la tabla anterior y también su restricción para la copia de seguridad.
/* 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
En SQL Server puede activar y desactivar la inserción de identidad de esta manera:
SET IDENTITY_INSERT table_name ON
- ejecuta tus consultas aquí
SET IDENTITY_INSERT table_name OFF