Adicionando uma identidade a uma coluna existente

445

Preciso alterar a chave primária de uma tabela para uma coluna de identidade, e já existe um número de linhas na tabela.

Eu tenho um script para limpar os IDs para garantir que eles sejam seqüenciais a partir de 1, funcionem bem no meu banco de dados de teste.

Qual é o comando SQL para alterar a coluna para ter uma propriedade de identidade?

Kirschstein
fonte

Respostas:

482

Você não pode alterar as colunas existentes para identidade.

Você tem 2 opções,

  1. Crie uma nova tabela com identidade e solte a tabela existente

  2. Crie uma nova coluna com identidade e solte a coluna existente

Abordagem 1. ( Nova tabela ) Aqui você pode reter os valores de dados existentes na coluna de identidade recém-criada.

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'

Abordagem 2 ( Nova coluna ) Você não pode reter os valores de dados existentes na coluna de identidade recém-criada. A coluna de identidade manterá a sequência do número.

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 a seguinte publicação no Fórum do Microsoft SQL Server para obter mais detalhes:

Como alterar a coluna para identidade (1,1)

John Sansom
fonte
49
Se os dados da tabela forem pequenos, esta opção funcionará bem. Se a tabela for grande, há outra opção que eu prefiro: use ALTER TABLE ... SWITCH para substituir o esquema da tabela por outra versão por uma coluna IDENTITY, mas por outro esquema idêntico. A vantagem da abordagem ALTER TABLE .... SWITCH é que ela é concluída rapidamente (menos de 5 segundos para uma tabela de bilhões de linhas), pois nenhum dado da tabela precisa ser copiado ou alterado. Existem advertências e limitações. Veja minha resposta abaixo para obter detalhes.
Justin Grant
7
@ Justin Grat: Uma alternativa muito interessante e que eu não tinha considerado! A razão pela qual isso funciona é porque IDENTITY é uma propriedade de coluna e não um tipo de dados; portanto, o método SWITCH valida os esquemas entre as duas tabelas (antigas e novas) como identificáveis, independentemente da diferença de IDENTITY. Obrigado por compartilhar!
John Sansom
Se você não tiver muitos dados, a "criação da tabela" poderá ser alcançada gerando um script a partir do SSMS. Clique com o botão direito do mouse na tabela> Tabela de scripts como> Criar TABELA para> (novo editor de consultas?). Em seguida, solte-o, e dentro desse script você pode adicionar a IDENTITY(1, 1)parte com a chave primária de coluna
goamn
Pode-se também usar o SSMS para impor isso. Vá para Ferramentas> Opções> Designers> Desmarque a opção "Impedir salvar alterações que exigem a recriação da tabela". BTW, isso não é recomendado para tabelas bastante grandes.
Zafar
No PostgreSQL, você pode adicionar identidade a uma coluna inteira existente com o comando: alterar tabela {nome_tabela} alterar coluna {nome_coluna} adicionar gerado sempre como identidade (reinicie com {número});
Andrew Mackie
209

No SQL 2005 e acima, há um truque para resolver esse problema sem alterar as páginas de dados da tabela. Isso é importante para tabelas grandes em que tocar em todas as páginas de dados pode levar minutos ou horas. O truque também funciona mesmo que a coluna de identidade seja uma chave primária, faça parte de um índice em cluster ou não em cluster ou outras dicas que podem desencadear a solução mais simples de "adicionar / remover / renomear coluna".

Aqui está o truque: você pode usar o ALTER TABLE ... do SQL Server para alterar o esquema de uma tabela sem alterar os dados, o que significa que você pode substituir uma tabela por uma IDENTITY por um esquema de tabela idêntico, mas sem uma coluna IDENTITY. O mesmo truque funciona para adicionar IDENTITY a uma coluna existente.

Normalmente, ALTER TABLE ... SWITCH é usado para substituir eficientemente uma partição completa em uma tabela particionada por uma nova partição vazia. Mas também pode ser usado em tabelas não particionadas.

Usei esse truque para converter, em menos de 5 segundos, uma coluna de uma tabela de linhas de 2,5 bilhões de IDENTITY para uma não-IDENTITY (para executar uma consulta de várias horas cujo plano de consulta funcionou melhor para não-IDENTITY colunas) e, em seguida, restaurou a configuração IDENTITY, novamente em menos de 5 segundos.

Aqui está um exemplo de código de como ele 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, isso está mais envolvido do que as soluções de outras respostas, mas se sua mesa for grande, isso pode salvar a vida de verdade. Existem algumas advertências:

  • Tanto quanto sei, a identidade é a única coisa que você pode alterar nas colunas da sua tabela com esse método. Não é permitido adicionar / remover colunas, alterar a nulidade etc.
  • Você precisará soltar as chaves estrangeiras antes de fazer a troca e restaurá-las depois.
  • O mesmo para as funções, visualizações, etc. com WITH SCHEMABINDING
  • os índices da nova tabela precisam corresponder exatamente (mesma coluna, mesma ordem etc.)
  • As tabelas antigas e novas precisam estar no mesmo grupo de arquivos.
  • Funciona apenas no SQL Server 2005 ou posterior
  • Anteriormente, eu acreditava que esse truque só funciona nas edições Enterprise ou Developer do SQL Server (porque as partições são suportadas apenas nas versões Enterprise e Developer), mas Mason G. Zhwiti em seu comentário abaixo diz que também funciona no SQL Standard Edition. Suponho que isso signifique que a restrição ao Enterprise ou Developer não se aplique ao ALTER TABLE ... SWITCH.

Há um bom artigo no TechNet detalhando os requisitos acima.

ATUALIZAÇÃO - Eric Wu fez um comentário abaixo que adiciona informações importantes sobre esta solução. Copie-o aqui para garantir mais atenção:

Há outra ressalva aqui que vale a pena mencionar. Embora a nova tabela receba com satisfação dados da tabela antiga e todas as novas linhas sejam inseridas seguindo um padrão de identidade, elas serão iniciadas em 1 e potencialmente serão interrompidas se a referida coluna for uma chave primária. Considere executar DBCC CHECKIDENT('<newTableName>')imediatamente após a troca. Consulte msdn.microsoft.com/en-us/library/ms176057.aspx para obter mais informações.

Se a tabela estiver ativamente sendo estendida com novas linhas (o que significa que você não tem muito tempo de inatividade entre adicionar IDENTITY e adicionar novas linhas, em vez de DBCC CHECKIDENTquerer definir manualmente o valor de propagação de identidade no novo esquema da tabela a ser maior que o maior ID existente na tabela, por exemplo, IDENTITY (2435457, 1)você pode incluir a transação ALTER TABLE...SWITCHe a DBCC CHECKIDENTtransação (ou não - não testou isso), mas parece que definir o valor da semente manualmente será mais fácil e seguro.

Obviamente, se nenhuma nova linha estiver sendo adicionada à tabela (ou apenas adicionada ocasionalmente, como um processo diário de ETL), essa condição de corrida não acontecerá, então tudo DBCC CHECKIDENTbem.

Justin Grant
fonte
5
Se minha memória está correta, eu tive a idéia deste artigo: sqlservercentral.com/articles/T-SQL/61979
Justin Grant
2
Para sua informação, isso também parece funcionar na versão padrão do SQL 2008 R2. Talvez eles tenham ativado esse recurso, assim como agora ativaram a capacidade de ativar a compactação de backup.
Mason G. Zhwiti
3
@jbatista - a pergunta do OP afirmou que ele já tinha uma chave primária em cima da mesa e já podia garantir os valores certos, mas ele simplesmente queria alterá-la para ser uma coluna de IDENTIDADE. Minha resposta acima está focada nesse caso de uso restrito: como adicionar a IDENTITY a uma coluna sem alterar realmente nenhum dado. A abordagem que documento acima é uma enorme economia de tempo para tabelas grandes. Se você precisar alterar dados, precisará usar outras soluções.
Justin Grant
3
Há outra ressalva aqui que vale a pena mencionar. Embora a nova tabela receba com satisfação dados da tabela antiga e todas as novas linhas sejam inseridas seguindo um padrão de identidade, elas começarão em 1 e potencialmente serão interrompidas se a coluna for uma chave primária. Considere executar DBCC CHECKIDENT('<newTableName>')imediatamente após a troca. Consulte msdn.microsoft.com/en-us/library/ms176057.aspx para obter mais informações.
Eric Wu
3
Esta é uma ótima resposta! Observe também que a nulidade das colunas deve ser a mesma. Portanto, se você precisar alterar a nulidade de uma coluna, precisará fazê-lo posteriormente. O mesmo vale para restrições de PK. Eu também alterar o valor de identidade na criação da tabela para coincidir com a corrente máxima: IDENTIDADE (MaxiD + 1, 1)
Philippe
71

Você não pode alterar uma coluna para ser uma coluna IDENTITY. O que você precisará fazer é criar uma nova coluna, definida como uma IDENTIDADE desde o início, soltar a coluna antiga e renomear a nova para o nome antigo.

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
fonte
O parâmetro \ @objname é ambíguo ou o \ @objtype reivindicado (COLUMN) está errado.
Jenny O'Reilly
1
@ JennyO'Reilly: coloque isso em uma pergunta separada e mostre o comando completo que você está usando!
marc_s
2
Foi o procedimento sp_rename que estava falhando. Encontrei uma solução no stackoverflow pesquisando o texto do erro. Parece haver alguma regra rígida de sintaxe com colchetes, embora minha tabela não tenha caracteres especiais em seu nome.
Jenny O'Reilly
1
ou pode ser como: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' e 'ALTER TABLE (yourTable) ADICIONAR OldColumnName INT IDENTITY (1,1)', por que renomear: p
RK Sharma
Marc, eu tentei esse comando exato em uma tabela enorme (~ 300 mln linhas), mas parei o processo após ~ 10 min
Naomi
14

Há uma solução legal descrita aqui: SQL SERVER - Adicionar ou remover propriedade de identidade na coluna

Em resumo, edite manualmente sua tabela no SQL Manager, alterne a identidade, NÃO SALVE alterações, apenas mostre o script que será criado para as alterações, copie-o e use-o mais tarde.

Isso economiza muito tempo, porque (o script) contém todas as chaves estrangeiras, índices etc. relacionados à tabela que você altera. Escrevendo isso manualmente ... Deus não permita.

greenoldman
fonte
esta é a solução que eu usei - o SSMS gera o T-SQL para fazer a alteração ... faz isso criando uma nova tabela temporária com o mesmo design de esquema, copiando todas as linhas para ela, removendo a origem e renomeando . pode demorar um pouco para ser executado completamente, mas funcionou perfeitamente.
Mdelvecchio 6/07
Eu não acho que Pinal Dave está realmente dizendo que você precisa para executar o script que você gera, é apenas para mostrar o que fazer a mudança através da UI faz para você ...
Zack
Essa facilidade de script no SSMS (na alteração da definição de uma tabela) é realmente o único recurso correto ao documentar uma tabela particionada. O local mais apropriado 'task' -> 'script table' sempre se esqueça de criar um script para a função de particionamento!
Martijn van der Jagt 27/07/2015
1
Pode ser útil para alguém. Para obter o Script de alteração após as alterações. Clique com o botão direito do mouse na tabela no modo de design no SSMS e selecione a opção "Gerar script de alteração" e salve o script na unidade local
Vijai 23/01
11

Considere usar SEQUENCE em vez de IDENTITY .

No sql server 2014 (não sei sobre versões inferiores), você pode fazer isso simplesmente, usando a sequência.

CREATE SEQUENCE  sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;

ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name

A partir daqui: Sequência como valor padrão para uma coluna

Oto Shavadze
fonte
6

Explicação simples

Renomeie a coluna existente usando sp_RENAME

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

Exemplo para renomear:

A coluna existente UserID é renomeada como OldUserID

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

Em seguida, adicione uma nova coluna usando alter query para definir como chave primária e valor de identidade

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

Exemplo para Definir chave primária

O novo nome da coluna criada é UserID

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

Solte a coluna renomeada

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Exemplo de coluna renomeada Drop

ALTER TABLE Users DROP COLUMN OldUserID

Agora, adicionamos uma chave primária e identidade à coluna existente na tabela.

Sathish Chelladurai
fonte
5

Eu sou um desenvolvedor java que, por acaso, entrou em uma equipe sem um DBA e onde, como desenvolvedor, não posso obter direitos de DBA. Fui encarregado de mover um esquema inteiro entre dois bancos de dados; portanto, sem ter um DBA, tive que fazê-lo executando scripts, não podendo usar a GUI no SQL Server 2008 porque não tinha privilégios de administrador.

Tudo foi movido sem problemas, no entanto, ao executar um procedimento armazenado no novo schema.table, descobri que perdi o campo de identidade em uma tabela. Verifiquei novamente o script que criou a tabela e ele estava lá, no entanto, o SQL Server não o obteve quando executei o script. Mais tarde, fui informado por um DBA que ele já havia visto esse mesmo problema antes.

De qualquer forma, para o SQL Server 2008, estas são as etapas que tomei para resolver isso e funcionaram, por isso estou postando isso aqui na esperança de que seja uma ajuda para alguém. Isto é o que eu fiz, pois tinha dependências do FK em outra tabela que tornava isso mais difícil:

Eu usei essa consulta para verificar se a identidade estava realmente ausente e para visualizar dependências na tabela.

1.) Encontre estatísticas em uma tabela:

exec sp_help 'dbo.table_name_old';

2.) Crie uma nova tabela idêntica e duplicada, exceto adicione um campo de identidade no campo PK onde estava antes.

3.) Desative a identidade para mover dados.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Transfira os dados.

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

5.) Verifique se os dados estão lá.

SELECT * FROM dbo.table_name_new

6.) Reative a identidade.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Este é o melhor script que encontrei para obter todos os relacionamentos do FK para verificar quais tabelas a tabela original faz referência como dependências e me deparei com muitas, por isso é um guardião!

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.) Verifique se você possui todos os scripts PK e FK para todas as tabelas envolvidas, antes desta próxima etapa.

9.) Você pode clicar com o botão direito do mouse em cada chave e criar um script usando o SQL Server 2008

10.) Solte o FK (s) da (s) tabela (s) de dependência usando esta sintaxe:

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

11.) Solte a tabela original:

DROP TABLE dbo.table_name_old;

13.) Essas próximas etapas dependem dos scripts que você criou no SQL Server 2008 na etapa 9.

--Adicione o PK à nova tabela.

--Adicione o FK à nova tabela.

--Adicione os FKs de volta à tabela de dependência.

14.) Verifique se tudo está correto e completo. Eu usei a GUI para olhar as tabelas.

15.) Renomeie a nova tabela com o nome da tabela original.

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

Finalmente, tudo funcionou!

James Drinkard
fonte
4

você não pode fazê-lo dessa maneira, é necessário adicionar outra coluna, soltar a coluna original e renomear a nova coluna ou criar uma nova tabela, copiar os dados e soltar a tabela antiga e renomear a nova tabela para a antiga. mesa

se você usa o SSMS e define a propriedade de identidade como ON no designer, aqui está o que o SQL Server faz nos bastidores. Portanto, se você tiver uma tabela chamada [user], é isso que acontece se você criar UserID e identidade

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

Dito isto, existe uma maneira de hackear a tabela do sistema para realizá-la, definindo o valor bit a bit, mas isso não é suportado e eu não faria isso

SQLMenace
fonte
4

Como eu entendi em casos normais, estamos criando uma tabela com Chave primária que está tendo a propriedade Identity.
Portanto, Renomear ou Excluir uma coluna associada à restrição de Chave primária não será possível porque as Regras de restrição estão validando a estrutura da coluna. Para conseguir isso, precisamos processar algumas etapas da seguinte maneira: Vamos assumir TableName = 'Employee' e ColumnName = 'EmployeeId' 1. Adicione uma nova coluna 'EmployeeId_new' na tabela 'Employee' ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY ( 1,1)




  1. Agora remova a coluna 'EmployeeId' da tabela 'Employee'
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Isso gerará erro devido às regras de restrição de chave primária serem aplicáveis ​​e à validação da estrutura da coluna.
    * ### ' Msg 5074, Nível 16, Estado 1, Linha 1 O objeto [PK_dbo.Employee] depende da colmn [EmployeeId].' ###

  3. Portanto, temos que remover primeiro a restrição de chave primária da tabela 'Employee', para remover a coluna
    Restrição ALTER TABLE Employee DROP [PK_dbo.Employee]

  4. Agora podemos remover a coluna 'EmployeeId' da tabela 'Employee', como ocorreu na etapa anterior, onde ocorreu o erro
    ALTER TABLE Employee DROP COLUMN EmployeeId

  5. Agora a coluna 'EmployeeId' foi removida da tabela. Renomearemos a nova coluna recém-adicionada 'EmployeeId_new' com 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN'

  6. Para reorganizar a tabela da mesma forma que era, precisamos adicionar a restrição de chave primária para a coluna 'EmployeeId'
    ALTER TABLE Employee adicionar restrição [PK_dbo.Employee] chave primária (EmployeeId)

8. Agora a tabela 'Employee' com 'EmployeeId' é modificada para regras de identidade junto com a restrição de chave primária existente

Nagendra Upwanshi
fonte
3

Por design, não há uma maneira simples de ativar ou desativar o recurso de identidade de uma coluna existente. A única maneira limpa de fazer isso é criar uma nova coluna e torná-la uma coluna de identidade ou criar uma nova tabela e migrar seus dados.

Se usarmos o SQL Server Management Studio para se livrar do valor da identidade na coluna "id", uma nova tabela temporária será criada, os dados serão movidos para a tabela temporária, a tabela antiga será descartada e a nova tabela será renomeada.

Use o Management Studio para fazer a alteração e clique com o botão direito do mouse no designer e selecione "Gerar script de alteração".

Você verá que é isso que o SQL Server está fazendo em segundo plano.

Raj
fonte
2

Infelizmente não há um; a propriedade IDENTITY pertence à tabela e não à coluna.

A maneira mais fácil é fazer isso na GUI, mas se isso não for uma opção, você pode percorrer um longo caminho ao copiar os dados, soltar a coluna, adicioná-los novamente com identidade e colocar os dados de volta.

Veja aqui uma conta golpe por golpe.

Jeremy Smyth
fonte
2

Clique com o botão direito do mouse no nome da tabela no Pesquisador de Objetos. Você receberá algumas opções. Clique em 'Design'. Uma nova guia será aberta para esta tabela. Você pode adicionar restrição de identidade aqui em 'Propriedades da coluna'.

vamsi_874
fonte
2

Para modificar as propriedades de identidade de uma coluna:

  • No Server Explorer, clique com o botão direito do mouse na tabela com propriedades de identidade que você deseja modificar e clique em Abrir Definição de Tabela. A tabela é aberta no Table Designer.
  • Desmarque a caixa de seleção Permitir nulos para a coluna que você deseja alterar.
  • Na guia Propriedades da coluna, expanda a propriedade Especificação de identidade.
  • Clique na célula da grade da propriedade filho É Identidade e escolha Sim na lista suspensa.
  • Digite um valor na célula Identity Seed. Este valor será atribuído à primeira linha da tabela. O valor 1 será atribuído por padrão.

É isso aí, e funcionou para mim

Ken.Fukizi
fonte
2

Se você estiver usando o Visual Studio 2017+

  1. No Server Object Explorer, clique com o botão direito na sua tabela e selecione "ver código"
  2. Adicione o modificador "IDENTITY" à sua coluna
  3. Atualizar

Isso fará tudo por você.

jdisla
fonte
Sim! Obrigado por sugerir isso! Não tenho uma versão do SSMS na minha caixa do Windows 7 que me permita fazer alterações de design nas tabelas no servidor de produção porque é 2017, meu SSMS é 2014 e o SSMS de 2017 precisa do Windows 10. Você fez o meu dia. Entrou no VS 2017> Server Explorer> fez uma nova conexão com a produção do SQL Server> clique com o botão direito do mouse na tabela> "Open Table Definition"> Wala!
JustJohn
Na verdade, eu achei que você pode clique direito sobre o campo e selecione Propriedades e fazer a identidade lá escolhendo Sim ou Não
JustJohn
1

Se o pôster original estava realmente querendo definir uma coluna existente para ser a PRIMARY KEYda tabela e, na verdade, não precisava que a coluna fosse uma IDENTITYcoluna (duas coisas diferentes), isso pode ser feito via t-SQL com:

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

Observe os parênteses ao redor do nome da coluna após a PRIMARY KEYopção.

Embora esta publicação seja antiga e eu suponha que os solicitantes precisam, achei que essas informações adicionais poderiam ser úteis para os usuários que encontrarem esse segmento, pois acredito que a conversa possa levar a pessoa a acreditar que uma coluna existente não pode ser configurada como chave primária sem adicioná-la como uma nova coluna primeiro, o que estaria incorreto.

A. Omalley
fonte
1

De acordo com minha condição atual, sigo essa abordagem. Quero dar identidade a uma tabela principal após os dados inseridos via script.

Como eu quero acrescentar uma identidade, ela sempre começa de 1 a Fim da contagem de registros que eu quero.

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

Isso criará a mesma coluna de chave primária com identidade

Eu usei esses links: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Adicionar chave primária à tabela existente

Ajay2707
fonte
0

Não acredito que você possa alterar uma coluna existente para ser uma coluna de identidade usando o tsql. No entanto, você pode fazê-lo através da visualização de design do Enterprise Manager.

Como alternativa, você pode criar uma nova linha como a coluna de identidade, soltar a coluna antiga e renomear sua nova coluna.

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED
William Edmondson
fonte
2
lembre-se de que, se você fizer isso através do SSMS / Enterprise Manager - estará criando uma nova tabela, copiando dados, descartando a tabela antiga e renomeando a nova. Isso pode ser bastante caro quando você tem grandes tabelas ...
Scott Ivey
0

Basicamente, existem quatro etapas lógicas.

  1. Crie uma nova coluna de identidade. Ative Inserir identidade para esta nova coluna.

  2. Insira os dados da coluna de origem (a coluna que você deseja converter em identidade) nessa nova coluna.

  3. Desative a Inserir identidade para a nova coluna.

  4. Solte sua coluna de origem e renomeie a nova coluna para o nome da coluna de origem.

Pode haver mais complexidade, como trabalhar em vários servidores, etc.

Consulte o seguinte artigo para as etapas (usando ssms e T-sql). Essas etapas são destinadas a iniciantes com menos domínio do T-SQL.

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

Shivalik Chakravarty
fonte
0

gera um script para todas as tabelas com chave primária = bigint que não possuem um conjunto de identidades; isso retornará uma lista de scripts gerados com cada tabela;

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
fonte