Agregar una identidad a una columna existente


445

Necesito cambiar la clave principal de una tabla a una columna de identidad, y ya hay varias filas en la tabla.

Tengo un script para limpiar las ID para garantizar que sean secuenciales a partir de 1, funciona bien en mi base de datos de prueba.

¿Cuál es el comando SQL para alterar la columna para tener una propiedad de identidad?

Respuestas:


482

No puede alterar las columnas existentes para la identidad.

Tienes 2 opciones,

  1. Cree una nueva tabla con identidad y descarte la tabla existente

  2. Cree una nueva columna con identidad y suelte la columna existente

Enfoque 1. ( Nueva tabla ) Aquí puede conservar los valores de datos existentes en la columna de identidad recién creada.

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'

Enfoque 2 ( Nueva columna ) No puede retener los valores de datos existentes en la columna de identidad recién creada. La columna de identidad contendrá la secuencia de números.

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'

Consulte la siguiente publicación del foro de Microsoft SQL Server para obtener más detalles:

Cómo alterar la columna a identidad (1,1)


49
Si los datos de la tabla son pequeños, esta opción funciona muy bien. Si la tabla es grande, hay otra opción que prefiero: use ALTER TABLE ... SWITCH para reemplazar el esquema de la tabla con otra versión con una columna IDENTITY pero, por lo demás, un esquema idéntico. La ventaja del enfoque ALTER TABLE .... SWITCH es que se completa rápidamente (menos de 5 segundos para una tabla de miles de millones de filas) ya que no es necesario copiar ni cambiar los datos de la tabla. Sin embargo, hay advertencias y limitaciones. Vea mi respuesta a continuación para más detalles.
Justin Grant

77
@Justin Grat: ¡Una alternativa muy interesante y que no había considerado! La razón por la que esto funciona es porque IDENTITY es una propiedad de columna y no un tipo de datos, por lo que el método SWITCH valida los esquemas entre las dos tablas (antigua y nueva) como identificables independientemente de la diferencia IDENTITY. ¡Gracias por compartir!
John Sansom el

Si no tiene muchos datos, se puede "crear la tabla" generando un script desde SSMS. Haga clic derecho en la tabla> Tabla de secuencias de comandos como> Crear TABLA a> (¿nuevo editor de consultas?). Luego suéltelo, y dentro de esa secuencia de comandos puede agregar la IDENTITY(1, 1)parte con la columna de la clave primaria
goamn

También se puede usar SSMS para hacer cumplir esto. Vaya a Herramientas> Opciones> Diseñadores> Desmarque "Evitar guardar cambios que requieren la recreación de la tabla". Por cierto, esto no se recomienda para tablas bastante grandes.
Zafar

En PostgreSQL puede agregar identidad a una columna entera existente con el comando: alter table {table_name} alter column {column_name} add generado siempre como identidad (reiniciar con {número});
Andrew Mackie

209

En SQL 2005 y versiones posteriores, hay un truco para resolver este problema sin cambiar las páginas de datos de la tabla. Esto es importante para tablas grandes donde tocar cada página de datos puede llevar minutos u horas. El truco también funciona incluso si la columna de identidad es una clave principal, es parte de un índice agrupado o no agrupado, u otras trampas que pueden disparar la solución más simple de "agregar / eliminar / renombrar columna".

Aquí está el truco: puede usar la instrucción ALTER TABLE ... SWITCH de SQL Server para cambiar el esquema de una tabla sin cambiar los datos, lo que significa que puede reemplazar una tabla con una IDENTIDAD con un esquema de tabla idéntico, pero sin una columna IDENTIDAD. El mismo truco funciona para agregar IDENTIDAD a una columna existente.

Normalmente, ALTER TABLE ... SWITCH se usa para reemplazar eficientemente una partición completa en una tabla particionada con una nueva partición vacía. Pero también se puede usar en tablas no particionadas.

He usado este truco para convertir, en menos de 5 segundos, una columna de una tabla de 2.500 millones de filas de IDENTIDAD a no IDENTIDAD (para ejecutar una consulta de varias horas cuyo plan de consulta funcionó mejor para no IDENTIDAD columnas), y luego restableció la configuración IDENTIDAD, nuevamente en menos de 5 segundos.

Aquí hay una muestra de código de cómo funciona.

 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; 

Obviamente, esto es más complicado que las soluciones en otras respuestas, pero si su tabla es grande, puede ser un verdadero salvavidas. Hay algunas advertencias:

  • Hasta donde sé, la identidad es lo único que puede cambiar sobre las columnas de su tabla con este método. No se permite agregar / eliminar columnas, cambiar la nulabilidad, etc.
  • Tendrá que soltar las llaves extranjeras antes de hacer el cambio y restaurarlas después.
  • Lo mismo para las funciones, vistas, etc. de WITH SCHEMABINDING.
  • los nuevos índices de la tabla deben coincidir exactamente (mismas columnas, mismo orden, etc.)
  • Las tablas antiguas y nuevas deben estar en el mismo grupo de archivos.
  • Solo funciona en SQL Server 2005 o posterior
  • Anteriormente creía que este truco solo funciona en las ediciones Enterprise o Developer de SQL Server (porque las particiones solo son compatibles con las versiones Enterprise y Developer), pero Mason G. Zhwiti en su comentario a continuación dice que también funciona en SQL Standard Edition. Supongo que esto significa que la restricción para Enterprise o Developer no se aplica a ALTER TABLE ... SWITCH.

Hay un buen artículo en TechNet que detalla los requisitos anteriores.

ACTUALIZACIÓN: Eric Wu hizo un comentario a continuación que agrega información importante sobre esta solución. Copiéndola aquí para asegurarse de que reciba más atención:

Hay otra advertencia aquí que vale la pena mencionar. Aunque la nueva tabla recibirá felizmente datos de la tabla anterior, y todas las nuevas filas se insertarán siguiendo un patrón de identidad, comenzarán en 1 y posiblemente se rompan si dicha columna es una clave primaria. Considere correr DBCC CHECKIDENT('<newTableName>')inmediatamente después de cambiar. Consulte msdn.microsoft.com/en-us/library/ms176057.aspx para obtener más información.

Si la tabla se está extendiendo activamente con nuevas filas (lo que significa que no tiene mucho tiempo de inactividad entre agregar IDENTIDAD y agregar nuevas filas, en lugar de DBCC CHECKIDENTque desee establecer manualmente el valor de origen de identidad en el nuevo esquema de tabla para más grande que la ID existente más grande en la tabla, por ejemplo, IDENTITY (2435457, 1)es posible que pueda incluir tanto el ALTER TABLE...SWITCHy el DBCC CHECKIDENTen una transacción (o no, no lo he probado), pero parece que establecer el valor inicial manualmente será más fácil y seguro.

Obviamente, si no se agregan nuevas filas a la tabla (o solo se agregan ocasionalmente, como un proceso diario de ETL), esta condición de carrera no sucederá, por lo que DBCC CHECKIDENTestá bien.


55
Si mi memoria es correcta, se me ocurrió la idea de este artículo: sqlservercentral.com/articles/T-SQL/61979
Justin Grant

2
Para su información, esto parece funcionar también en la versión estándar de SQL 2008 R2. Quizás habilitaron esta función al igual que ahora han habilitado la capacidad de activar la compresión de respaldo.
Mason G. Zhwiti

3
@jbatista: la pregunta del OP indicaba que ya tenía una clave principal sobre la mesa y que ya podía garantizar los valores correctos, pero simplemente quería cambiarla para que fuera una columna IDENTIDAD. Mi respuesta anterior se centra en ese caso de uso limitado: cómo agregar la IDENTIDAD a una columna sin cambiar realmente ningún dato. El enfoque que documente arriba es un gran ahorro de tiempo para tablas grandes. Si necesita cambiar los datos, deberá usar otras soluciones.
Justin Grant

3
Hay otra advertencia aquí que vale la pena mencionar. Aunque la nueva tabla recibirá felizmente los datos de la tabla anterior, y todas las nuevas filas se insertarán siguiendo un patrón de identidad, comenzarán en 1 y posiblemente se rompan si dicha columna es una clave principal. Considere correr DBCC CHECKIDENT('<newTableName>')inmediatamente después de cambiar. Consulte msdn.microsoft.com/en-us/library/ms176057.aspx para obtener más información.
Eric Wu

3
¡Esta es una respuesta genial! También tenga en cuenta que la nulabilidad de las columnas debe ser la misma. Entonces, si necesita cambiar la anulabilidad de una columna, tendrá que hacerlo en un paso posterior. Lo mismo ocurre con las restricciones de PK. También cambio el valor de identidad en la creación de la tabla para que coincida con el máximo actual: IDENTIDAD (maxID + 1, 1)
Philippe

71

No puede modificar una columna para que sea una columna IDENTIDAD. Lo que tendrá que hacer es crear una nueva columna que se define como una IDENTIDAD desde el principio, luego suelte la columna anterior y cambie el nombre de la nueva por el nombre anterior.

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

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

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

Bagazo


O el parámetro \ @objname es ambiguo o el \ @objtype (COLUMN) reclamado es incorrecto.
Jenny O'Reilly

1
@ JennyO'Reilly: poner esto en una cuestión aparte, y mostrarnos el comando completo que está utilizando!
marc_s

2
Fue el procedimiento sp_rename que estaba fallando. Encontré una solución en stackoverflow buscando el texto de error. Parece ser una regla de sintaxis estricta entre paréntesis, aunque mi tabla no tiene caracteres especiales en su nombre.
Jenny O'Reilly

1
o podría ser como: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' y 'ALTER TABLE (yourTable) ADD OldColumnName INT IDENTITY (1,1)', por qué cambiar el nombre: p
RK Sharma

Marc, probé este comando exacto en una tabla enorme (~ 300 mln de filas), pero detuve el proceso después de ~ 10 min
Naomi

14

Aquí se describe una solución interesante: SERVIDOR SQL - Agregar o quitar propiedad de identidad en la columna

En resumen, edite manualmente su tabla en SQL Manager, cambie la identidad, NO GUARDE los cambios, solo muestre el script que se creará para los cambios, cópielo y úselo más tarde.

Es un gran ahorro de tiempo, ya que (el script) contiene todas las claves externas, índices, etc. relacionados con la tabla que cambia. Escribiendo esto manualmente ... Dios no lo quiera.


esta es la solución que utilicé: SSMS genera el T-SQL para realizar el cambio ... lo hace creando una nueva tabla temporal del mismo diseño de esquema, luego copiando todas las filas, eliminando el origen y renombrando . Puede tardar un poco en ejecutarse por completo, pero funcionó perfectamente.
mdelvecchio

No creo Pinal de Dave en realidad está diciendo que necesita para ejecutar la secuencia de comandos que se genera, es sólo para mostrar lo que es hacer el cambio a través de la interfaz de usuario hace por usted ...
Zack

Esta instalación de scripts en SSMS (al cambiar la definición de una tabla) es en realidad la única facilidad correcta al documentar una tabla particionada. La ubicación 'tarea' más adecuada -> 'tabla de script' siempre se olvida de ejecutar la función de partición.
Martijn van der Jagt

1
Puede ser útil para alguien. Para obtener la secuencia de comandos de cambio después de los cambios. Haga clic derecho en la tabla en modo de diseño en SSMS y seleccione la opción "Generar cambio de secuencia de comandos" y guarde la secuencia de comandos en la unidad local
Vijai


6

Explicación simple

Cambie el nombre de la columna existente usando sp_RENAME

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

Ejemplo para cambiar el nombre:

La columna existente UserID se renombra como OldUserID

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

Luego agregue una nueva columna usando la consulta alter para establecer como clave principal y valor de identidad

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

Ejemplo para establecer clave primaria

El nuevo nombre de columna creado es UserID

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

luego suelte la columna renombrada

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Ejemplo para soltar columna renombrada

ALTER TABLE Users DROP COLUMN OldUserID

Ahora hemos agregado una clave primaria y una identidad a la columna existente en la tabla.


5

Soy un desarrollador de Java que pasó a formar parte de un equipo sin un DBA y en el que, como desarrollador, no puedo obtener los derechos de DBA. Se me asignó la tarea de mover un esquema completo entre dos bases de datos, por lo que sin tener un DBA, tuve que hacerlo y hacerlo ejecutando scripts, no pudiendo usar la GUI en SQL Server 2008 porque no tenía privilegios de administrador.

Sin embargo, todo se movió sin problemas al ejecutar un procedimiento almacenado en el nuevo esquema.table, descubrí que perdí el campo de identidad en una tabla. Verifiqué dos veces el script que creó la tabla y estaba allí, sin embargo, SQL Server no lo obtuvo cuando ejecuté el script. Un DBA me dijo después que había visto este mismo problema antes.

En cualquier caso, para SQL Server 2008, estos son los pasos que tomé para resolver esto y funcionaron, así que estoy publicando esto aquí con la esperanza de que sea de ayuda para alguien. Esto es lo que hice, ya que tenía dependencias de FK en otra tabla que lo hizo más difícil:

Utilicé esta consulta para verificar que faltaba la identidad y para ver las dependencias en la tabla.

1.) Encuentra estadísticas en una tabla:

exec sp_help 'dbo.table_name_old';

2.) Cree una tabla nueva idéntica y duplicada, excepto que agregue un campo de identidad en el campo PK donde había estado antes.

3.) Desactiva la identidad para mover datos.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Transfiera los datos.

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

5.) Verifique que los datos estén allí.

SELECT * FROM dbo.table_name_new

6.) Vuelva a habilitar la identidad.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Este es el mejor script que encontré para obtener todas las relaciones FK para verificar a qué tabla (s) hace referencia la tabla original como dependencias y encontré muchas, ¡así que es un guardián!

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.) Asegúrese de tener todos los scripts PK y FK para todas las tablas involucradas, antes del siguiente paso.

9.) Puede hacer clic con el botón derecho en cada tecla y escribir esto usando SQL Server 2008

10.) Descarte los FK de las tablas de dependencias utilizando esta sintaxis:

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

11.) Suelta la tabla original:

DROP TABLE dbo.table_name_old;

13.) Estos próximos pasos se basan en los scripts que creó en SQL Server 2008 en el paso 9.

--Agregue el PK a la nueva tabla.

--Agregue el FK a la nueva tabla.

--Agregue los FK de vuelta a la tabla de dependencias.

14.) Verifique que todo sea correcto y completo. Usé la GUI para mirar las tablas.

15.) Cambie el nombre de la nueva tabla al nombre de las tablas originales.

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

¡Finalmente, todo funcionó!


4

no puede hacerlo así, necesita agregar otra columna, soltar la columna original y cambiar el nombre de la nueva columna o crear una nueva tabla, copiar los datos y soltar la tabla anterior y luego renombrar la nueva tabla a la anterior mesa

si usa SSMS y establece la propiedad de identidad en ON en el diseñador, esto es lo que SQL Server hace detrás de escena. Entonces, si tiene una tabla llamada [usuario], esto es lo que sucede si crea ID de usuario e identidad

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

Habiendo dicho eso, hay una manera de hackear la tabla del sistema para lograrlo estableciendo el valor bit a bit, pero eso no es compatible y no lo haría


4

Como entendí en casos normales, estamos creando una tabla con la clave primaria que tiene la propiedad de identidad.
Por lo tanto, cambiar el nombre o eliminar una columna asociada con la restricción de la clave primaria no será posible porque las reglas de restricción están validando la estructura de la columna.
Para lograr esto, tenemos que procesar algunos pasos de la siguiente manera:
Supongamos que TableName = 'Employee' y ColumnName = 'EmployeeId'

1. Agregue una nueva columna 'EmployeeId_new' en la tabla 'Employee'
ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY ( 1,1)

  1. Ahora elimine la columna 'EmployeeId' de la tabla 'Employee'.
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Esto arrojará un error debido a que las reglas de restricción de clave primaria son aplicables y validan la estructura de la columna.
    * ### ' Mensaje 5074, Nivel 16, Estado 1, Línea 1 El objeto [PK_dbo.Employee] depende de colmn [EmployeeId].' ###

  3. Por lo tanto, primero debemos eliminar la restricción de la clave principal de la tabla 'Empleado' y luego podemos eliminar la columna
    ALTER TABLE. Restricción DROP del empleado [PK_dbo.Employee]

  4. Ahora podemos eliminar la columna 'EmployeeId' de la tabla 'Employee' como lo hizo en el paso anterior donde obtuvimos el error
    ALTER TABLE Employee DROP COLUMN EmployeeId

  5. Ahora se elimina la columna 'EmployeeId' de la tabla, así que cambiaremos el nombre de la nueva columna recién agregada 'EmployeeId_new' con 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN'

  6. Para reorganizar la tabla en la misma forma en que estaba, tenemos que agregar la restricción de clave primaria para la columna 'EmployeeId'.
    ALTER TABLE Empleado agregar restricción [PK_dbo.Employee] clave primaria (EmployeeId)

8. Ahora la tabla 'Empleado' con 'Id. De empleado' se modifica para las reglas de identidad junto con la restricción de clave principal existente


3

Por diseño, no hay una manera simple de activar o desactivar la función de identidad para una columna existente. La única forma limpia de hacerlo es crear una nueva columna y convertirla en una columna de identidad o crear una nueva tabla y migrar sus datos.

Si utilizamos SQL Server Management Studio para eliminar el valor de identidad en la columna "id", se crea una nueva tabla temporal, los datos se mueven a la tabla temporal, la tabla anterior se descarta y la nueva tabla se renombra.

Use Management Studio para realizar el cambio y luego haga clic derecho en el diseñador y seleccione "Generar secuencia de comandos de cambio".

Verá que esto es lo que el servidor SQL está haciendo en segundo plano.


2

No hay uno, lamentablemente; la propiedad IDENTITY pertenece a la tabla en lugar de a la columna.

La forma más fácil es hacerlo en la GUI, pero si esto no es una opción, puede recorrer el camino de copiar los datos, soltar la columna, volver a agregarlos con identidad y volver a colocar los datos.

Vea aquí para una cuenta de golpe por golpe.


2

Haga clic derecho en el nombre de la tabla en el Explorador de objetos. Obtendrás algunas opciones. Haga clic en 'Diseño'. Se abrirá una nueva pestaña para esta tabla. Puede agregar la restricción de identidad aquí en 'Propiedades de columna'.


2

Para modificar las propiedades de identidad de una columna:

  • En el Explorador de servidores, haga clic con el botón derecho en la tabla con las propiedades de identidad que desea modificar y haga clic en Abrir definición de tabla. La tabla se abre en Table Designer.
  • Desactive la casilla de verificación Permitir nulos para la columna que desea cambiar.
  • En la pestaña Propiedades de columna, expanda la propiedad Especificación de identidad.
  • Haga clic en la celda de la cuadrícula de la propiedad secundaria Es identidad y elija Sí en la lista desplegable.
  • Escriba un valor en la celda Semilla de identidad. Este valor se asignará a la primera fila de la tabla. El valor 1 se asignará por defecto.

Eso es todo, y funcionó para mí.


2

Si estás usando Visual Studio 2017+

  1. En Server Object Explorer, haga clic derecho en su tabla y seleccione "ver código"
  2. Agregue el modificador "IDENTIDAD" a su columna
  3. Actualizar

Esto lo hará todo por ti.


¡Si! ¡Gracias por sugerir esto! No tengo una versión de SSMS en mi cuadro de Windows 7 que me permita hacer cambios de diseño en las tablas de mi servidor de producción porque es 2017, mi SSMS es 2014 y 2017 SSMS necesita Windows 10. Me alegraron el día. Ingresó a VS 2017> Server Explorer> realizó una nueva conexión a SQL Server de producción> hizo clic con el botón derecho en la tabla> "Abrir definición de tabla"> Wala!
JustJohn

En realidad, descubrí que puede hacer clic derecho en el campo y seleccionar Propiedades y hacer la Identidad allí eligiendo Sí o No.
JustJohn

1

Si el póster original realmente deseaba establecer una columna existente para ser una PRIMARY KEYpara la tabla y realmente no necesitaba que la columna fuera una IDENTITYcolumna (dos cosas diferentes), esto se puede hacer a través de t-SQL con:

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

Tenga en cuenta el paréntesis alrededor del nombre de la columna después de la PRIMARY KEYopción.

Aunque esta publicación es antigua y estoy asumiendo la necesidad de los solicitantes, sentí que esta información adicional podría ser útil para los usuarios que se encuentran con este hilo, ya que creo que la conversación podría llevar a creer que una columna existente no se puede configurar como clave principal sin agregarla primero como una nueva columna, lo que sería incorrecto.


1

Según mi condición actual, sigo este enfoque. Quiero dar identidad a una tabla primaria después de que los datos se inserten a través del script.

Como quiero agregar identidad, siempre comienza del 1 al final del recuento de registros que quiero.

--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

Esto creará la misma columna de clave primaria con identidad

Usé estos enlaces: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Agregar clave principal a la tabla existente


0

No creo que pueda alterar una columna existente para que sea una columna de identidad usando tsql. Sin embargo, puede hacerlo a través de la vista de diseño de Enterprise Manager.

Alternativamente, podría crear una nueva fila como la columna de identidad, soltar la columna anterior y luego renombrar su nueva columna.

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED

2
tenga en cuenta que si lo hace a través de SSMS / Enterprise Manager, creará una nueva tabla, copiará datos, descartará la tabla anterior y cambiará el nombre de la nueva. Eso puede ser bastante costoso cuando tienes mesas grandes ...
Scott Ivey

0

Básicamente hay cuatro pasos lógicos.

  1. Crear una nueva columna de identidad. Active Insertar identidad para esta nueva columna.

  2. Inserte los datos de la columna de origen (la columna que desea convertir a Identidad) en esta nueva columna.

  3. Desactive Insertar identidad para la nueva columna.

  4. Suelte su columna fuente y cambie el nombre de la nueva columna al nombre de la columna fuente.

Puede haber algunas complejidades más como trabajar en varios servidores, etc.

Consulte el siguiente artículo para conocer los pasos (uso de ssms y T-sql). Estos pasos están destinados a principiantes con menos control sobre T-SQL.

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


0

genera un script para todas las tablas con clave primaria = bigint que no tienen un conjunto de identidad; esto devolverá una lista de scripts generados con cada tabla;

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;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.