Aggiunta di un'identità a una colonna esistente


445

Ho bisogno di cambiare la chiave primaria di una tabella in una colonna di identità, e c'è già un numero di righe nella tabella.

Ho uno script per ripulire gli ID per assicurarmi che siano sequenziali a partire da 1, funziona bene sul mio database di test.

Qual è il comando SQL per modificare la colonna per avere una proprietà identità?

Risposte:


482

Non è possibile modificare le colonne esistenti per l'identità.

Hai 2 opzioni,

  1. Crea una nuova tabella con identità e rilascia la tabella esistente

  2. Crea una nuova colonna con identità e rilascia la colonna esistente

Approccio 1. ( Nuova tabella ) Qui è possibile conservare i valori dei dati esistenti nella colonna identità appena creata.

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'

Approccio 2 ( Nuova colonna ) Non è possibile conservare i valori dei dati esistenti nella colonna Identità appena creata. La colonna Identità conterrà la sequenza numerica.

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'

Vedere il seguente post sul forum di Microsoft SQL Server per ulteriori dettagli:

Come modificare la colonna in identità (1,1)


49
Se i dati della tabella sono piccoli, questa opzione funziona. Se la tabella è grande, c'è un'altra opzione che preferisco: utilizzare ALTER TABLE ... SWITCH per sostituire lo schema della tabella con un'altra versione con una colonna IDENTITY ma schema altrimenti identico. Il vantaggio dell'approccio ALTER TABLE .... SWITCH è che si completa rapidamente (meno di 5 secondi per una tabella da un miliardo di righe) poiché non è necessario copiare o modificare i dati della tabella. Ci sono avvertimenti e limitazioni però. Vedi la mia risposta qui sotto per i dettagli.
Justin Grant,

7
@Justin Grat: un'alternativa molto interessante e che non avevo considerato! Il motivo per cui funziona è perché IDENTITY è una proprietà di colonna e non un tipo di dati, quindi il metodo SWITCH convalida gli schemi tra le due tabelle (vecchio e nuovo) come identificabili indipendentemente dalla differenza di IDENTITÀ. Grazie per la condivisione!
John Sansom,

Se non si dispone di molti dati, è possibile ottenere la "creazione della tabella" generando uno script da SSMS. Fare clic con il tasto destro del mouse sulla tabella> Scrip table come> Crea TABELLA in> (nuovo editor di query?). Quindi rilascialo e all'interno di quello script è possibile aggiungere la IDENTITY(1, 1)parte con la colonna chiave primaria
goamn

Si può anche usare SSMS per imporre questo. Vai su Strumenti> Opzioni> Designer> Deseleziona "Impedisci il salvataggio delle modifiche che richiedono la ricostruzione della tabella". A proposito, questo non è raccomandato per tavoli abbastanza grandi.
Zafar,

In PostgreSQL puoi aggiungere identità a una colonna intera esistente con il comando: alter table {table_name} alter column {column_name} aggiungi generato sempre come identità (riavvia con {numero});
Andrew Mackie,

209

In SQL 2005 e versioni successive, esiste un trucco per risolvere questo problema senza modificare le pagine di dati della tabella. Questo è importante per le tabelle di grandi dimensioni in cui il tocco di ogni pagina di dati può richiedere minuti o ore. Il trucco funziona anche anche se la colonna Identity è una chiave primaria, fa parte di un indice cluster o non cluster, o altri trucchi che possono far scattare la soluzione più semplice "aggiungi / rimuovi / rinomina colonna".

Ecco il trucco: puoi usare ALTER TABLE ... SWITCH di SQL Server per modificare lo schema di una tabella senza modificare i dati, il che significa che è possibile sostituire una tabella con un IDENTITY con uno schema di tabella identico, ma senza una colonna IDENTITY. Lo stesso trucco funziona per aggiungere IDENTITÀ a una colonna esistente.

Normalmente, ALTER TABLE ... SWITCH viene utilizzato per sostituire in modo efficiente una partizione completa in una tabella partizionata con una nuova partizione vuota. Ma può essere utilizzato anche in tabelle non partizionate.

Ho usato questo trucco per convertire, in meno di 5 secondi, una colonna di una tabella di 2,5 miliardi di righe da IDENTITÀ a non IDENTITÀ (al fine di eseguire una query di più ore il cui piano di query funzionava meglio per non IDENTITÀ colonne), quindi ripristinato l'impostazione IDENTITÀ, sempre in meno di 5 secondi.

Ecco un esempio di codice di come funziona.

 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; 

Questo è ovviamente più coinvolto rispetto alle soluzioni di altre risposte, ma se il tuo tavolo è grande questo può essere un vero salvavita. Ci sono alcuni avvertimenti:

  • Per quanto ne so, l'identità è l'unica cosa che puoi cambiare sulle colonne della tua tabella con questo metodo. L'aggiunta / rimozione di colonne, la modifica della nullità, ecc. Non è consentita.
  • Dovrai rilasciare le chiavi foriegn prima di fare il passaggio e ripristinarle dopo.
  • Lo stesso vale per le funzioni, le viste, ecc. CON SCHEMABINDING
  • gli indici della nuova tabella devono corrispondere esattamente (stesse colonne, stesso ordine, ecc.)
  • Le tabelle vecchie e nuove devono essere nello stesso filegroup.
  • Funziona solo su SQL Server 2005 o versioni successive
  • In precedenza credevo che questo trucco funzionasse solo sulle edizioni Enterprise o Developer di SQL Server (perché le partizioni sono supportate solo nelle versioni Enterprise e Developer), ma Mason G. Zhwiti nel suo commento qui sotto afferma che funziona anche in SQL Standard Edition. Presumo che ciò significhi che la restrizione a Enterprise o Developer non si applica a ALTER TABLE ... SWITCH.

C'è un buon articolo su TechNet che descrive in dettaglio i requisiti di cui sopra.

AGGIORNAMENTO - Eric Wu ha commentato di seguito un commento che aggiunge informazioni importanti su questa soluzione. Copiandolo qui per assicurarsi che riceva più attenzione:

C'è un altro avvertimento qui che vale la pena menzionare. Sebbene la nuova tabella riceverà felicemente i dati dalla vecchia tabella e tutte le nuove righe verranno inserite seguendo un modello di identità, esse inizieranno da 1 e potenzialmente si interromperanno se detta colonna è una chiave primaria. Valuta di correre DBCC CHECKIDENT('<newTableName>')subito dopo il passaggio. Vedere msdn.microsoft.com/en-us/library/ms176057.aspx per ulteriori informazioni.

Se la tabella viene attivamente estesa con nuove righe (il che significa che non hai molto tempo di inattività tra l'aggiunta di IDENTITÀ e l'aggiunta di nuove righe, allora invece di DBCC CHECKIDENTimpostare manualmente il valore del seme di identità nel nuovo schema della tabella più grande del più grande ID esistente nella tabella, ad es IDENTITY (2435457, 1). Potresti essere in grado di includere sia il ALTER TABLE...SWITCHche il DBCC CHECKIDENTin una transazione (oppure no-- non l'ho testato) ma sembra che l'impostazione manuale del valore di seed sia più semplice e sicura.

Ovviamente, se non vengono aggiunte nuove righe alla tabella (o vengono aggiunte solo occasionalmente, come un processo ETL giornaliero), allora questa condizione di gara non si verificherà, quindi DBCC CHECKIDENTva bene.


5
Se la mia memoria è corretta, ho preso l'idea da questo articolo: sqlservercentral.com/articles/T-SQL/61979
Justin Grant,

2
Cordiali saluti, questo sembra funzionare anche sulla versione standard di SQL 2008 R2. Forse hanno abilitato questa funzione proprio come hanno ora abilitato la possibilità di attivare la compressione del backup.
Mason G. Zhwiti,

3
@jbatista: la domanda del PO affermava che aveva già una chiave primaria nella tabella e che già poteva garantire i valori giusti, ma voleva semplicemente cambiarla in una colonna IDENTITÀ. La mia risposta sopra è focalizzata su un caso d'uso ristretto: come aggiungere l'IDENTITÀ a una colonna senza modificare effettivamente i dati. L'approccio che documento sopra è un enorme risparmio di tempo per le tabelle di grandi dimensioni. Se è necessario modificare i dati, è necessario utilizzare altre soluzioni.
Justin Grant,

3
C'è un altro avvertimento qui che vale la pena menzionare. Sebbene la nuova tabella riceverà felicemente i dati dalla vecchia tabella e tutte le nuove righe verranno inserite seguendo un modello di identità, esse inizieranno da 1 e potenzialmente si interromperanno se detta colonna è una chiave primaria. Valuta di correre DBCC CHECKIDENT('<newTableName>')subito dopo il passaggio. Vedere msdn.microsoft.com/en-us/library/ms176057.aspx per ulteriori informazioni.
Eric Wu

3
Questa è un'ottima risposta! Si noti inoltre che la nullità delle colonne deve essere la stessa. Quindi, se è necessario modificare la nullità di una colonna, è necessario farlo in un passaggio successivo. Lo stesso vale per i vincoli PK. Modifica anche il valore dell'identità nella creazione della tabella in modo che corrisponda al massimo corrente: IDENTITÀ (maxID + 1, 1)
Philippe

71

Non è possibile modificare una colonna in modo che sia una colonna IDENTITÀ. Quello che devi fare è creare una nuova colonna che è definita come IDENTITÀ fin dall'inizio, quindi eliminare la vecchia colonna e rinominare quella nuova con il vecchio nome.

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

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

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

Marc


Il parametro \ @objname è ambiguo o il preteso \ @objtype (COLUMN) è errato.
Jenny O'Reilly,

1
@ JennyO'Reilly: inseriscilo in una domanda separata e mostraci il comando completo che stai utilizzando!
marc_s,

2
Era la procedura sp_rename che non riusciva. Ho trovato una soluzione su StackOverflow cercando il testo dell'errore. Sembra essere una regola di sintassi rigorosa tra parentesi, anche se la mia tabella non ha caratteri speciali nel suo nome.
Jenny O'Reilly,

1
o potrebbe essere come: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' e 'ALTER TABLE (yourTable) ADD OldColumnName INT IDENTITY (1,1)', perché rinominare: p
RK Sharma

Marc, ho provato questo esatto comando su un enorme tavolo (~ 300 mln di righe), ma ho interrotto il processo dopo ~ 10 min
Naomi

14

C'è una soluzione interessante descritta qui: SQL SERVER - Aggiungi o rimuovi proprietà identità sulla colonna

In breve, modifica manualmente la tabella in SQL Manager, cambia l'identità, NON SALVARE le modifiche, mostra solo lo script che verrà creato per le modifiche, copiarlo e utilizzarlo in un secondo momento.

Fa risparmiare molto tempo, perché (lo script) contiene tutte le chiavi esterne, gli indici, ecc. Relativi alla tabella modificata. Scrivere questo manualmente ... Dio non voglia.


questa è la soluzione che ho usato - SSMS genera il T-SQL per apportare la modifica ... lo fa creando una nuova tabella temporanea con lo stesso schema, quindi copiando tutte le righe, rimuovendo l'orig e rinominando . può richiedere un po 'di tempo per funzionare completamente ma ha funzionato perfettamente.
mdelvecchio,

Non penso che Pinal Dave stia effettivamente dicendo che devi eseguire lo script che generi, è solo per mostrare ciò che fa il cambiamento attraverso l'interfaccia utente per te ...
Zack,

Questa funzionalità di scripting in SSMS (sulla modifica della definizione di una tabella) è in realtà l'unica funzione corretta quando si documenta una tabella partizionata. La posizione più appropriata 'task' -> 'tabella script' dimentica sempre di eseguire lo script della funzione di partizionamento!
Martijn van der Jagt,

1
Può essere utile a qualcuno. Per ottenere lo script di modifica dopo le modifiche. Fare clic destro sulla tabella in modalità progettazione su SSMS e selezionare l'opzione "Genera script di modifica" e salvare lo script nell'unità locale
Vijai


6

Spiegazione semplice

Rinomina la colonna esistente utilizzando sp_RENAME

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

Esempio per rinominare:

La colonna UserID esistente viene rinominata come OldUserID

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

Quindi aggiungere una nuova colonna usando alter query per impostare come chiave primaria e valore identità

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

Esempio per Imposta chiave primaria

Il nome della nuova colonna creata è UserID

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

quindi rilascia la colonna rinominata

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Esempio per Drop rinominato colonna

ALTER TABLE Users DROP COLUMN OldUserID

Ora abbiamo aggiunto una chiave primaria e un'identità alla colonna esistente sulla tabella.


5

Sono uno sviluppatore Java che è capitato di entrare in una squadra senza un DBA e uno in cui come sviluppatore, non posso ottenere i diritti DBA. Mi è stato assegnato il compito di spostare un intero schema tra due database, quindi senza avere un DBA, ho dovuto farlo e farlo eseguendo degli script, non potendo usare la GUI in SQL Server 2008 perché non avevo i privilegi di amministratore.

Tutto è stato spostato senza problemi, tuttavia, durante l'esecuzione di una procedura memorizzata sul nuovo schema.table, ho scoperto di aver perso il campo identità in una tabella. Ho ricontrollato lo script che ha creato la tabella ed era lì, tuttavia, SQL Server non l'ha capito quando ho eseguito lo script. In seguito mi è stato detto da un DBA che aveva già visto lo stesso problema in precedenza.

In ogni caso, per SQL Server 2008, questi sono i passi che ho fatto per risolverlo e hanno funzionato, quindi sto pubblicando questo qui nella speranza che possa essere di aiuto a qualcuno. Questo è quello che ho fatto perché avevo dipendenze FK su un altro tavolo che rendeva questo più difficile:

Ho usato questa query per verificare che mancasse davvero l'identità e per visualizzare le dipendenze sul tavolo.

1.) Trova le statistiche su una tabella:

exec sp_help 'dbo.table_name_old';

2.) Creare una nuova tabella duplicata e identica, tranne aggiungere un campo identità nel campo PK in cui era stato prima.

3.) Disabilitare l'identità per spostare i dati.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Trasferire i dati.

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

5.) Verificare che i dati siano presenti.

SELECT * FROM dbo.table_name_new

6.) Riattivare l'identità.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Questo è lo script migliore che ho trovato per ottenere tutte le relazioni FK per verificare quali tabelle fanno riferimento alla tabella originale come dipendenze e ne ho incontrate molte, quindi è un custode!

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.) Assicurati di avere tutti gli script PK e FK per tutte le tabelle coinvolte, prima di questo passaggio successivo.

9.) È possibile fare clic con il pulsante destro del mouse su ciascuna chiave e copiarla utilizzando SQL Server 2008

10.) Eliminare gli FK dalle tabelle delle dipendenze usando questa sintassi:

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

11.) Rilascia la tabella originale:

DROP TABLE dbo.table_name_old;

13.) Questi passaggi successivi si basano sugli script creati in SQL Server 2008 al passaggio 9.

- Aggiungi il PK alla nuova tabella.

- Aggiungi l'FK alla nuova tabella.

--Aggiunta dell'FK alla tabella delle dipendenze.

14.) Verifica che tutto sia corretto e completo. Ho usato la GUI per guardare le tabelle.

15.) Rinomina la nuova tabella con il nome originale delle tabelle.

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

Finalmente tutto ha funzionato!


4

non puoi farlo in questo modo, devi aggiungere un'altra colonna, rilasciare la colonna originale e rinominare la nuova colonna o o creare una nuova tabella, copiare i dati e rilasciare la vecchia tabella seguita da rinominare la nuova tabella nella vecchia tavolo

se si utilizza SSMS e si imposta la proprietà dell'identità su ON nella finestra di progettazione, ecco cosa fa SQL Server dietro le quinte. Quindi se hai una tabella chiamata [utente] questo è ciò che accade se crei UserID e identità

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

Detto questo, esiste un modo per hackerare la tabella di sistema per realizzarla impostando il valore bit per bit ma questo non è supportato e non lo farei


4

Come ho capito in casi normali, stiamo creando una tabella con chiave primaria che ha la proprietà Identity.
Quindi Rinomina o Elimina una colonna associata al vincolo Chiave primaria non sarà possibile perché le regole del vincolo stanno convalidando la struttura della colonna. Per raggiungere questo obiettivo dobbiamo elaborare alcuni passaggi nel modo seguente: Supponiamo TableName = 'Employee' e ColumnName = 'EmployeeId' 1. Aggiungi la nuova colonna 'EmployeeId_new' nella tabella 'Employee' ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY ( 1,1)




  1. Ora rimuovi la colonna 'EmployeeId' dalla tabella 'Employee'
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Questo genererà un errore a causa delle regole di vincolo chiave primaria applicabili e della struttura della colonna di convalida.
    * ### ' Messaggio 5074, livello 16, stato 1, riga 1 L'oggetto [PK_dbo.Employee] dipende da colmn [EmployeeId].' ###

  3. Quindi dobbiamo rimuovere prima il vincolo Chiave primaria dalla tabella "Dipendente", quindi possiamo rimuovere la colonna
    Vincolo DROP Dipendente Dipendente [PK_dbo.Employee]

  4. Ora è possibile rimuovere la colonna "EmployeeId" dalla tabella "Employee" come nel passaggio precedente in cui è stato visualizzato l'errore
    ALTER TABLE Employee DROP COLUMN EmployeeId

  5. Ora la colonna 'EmployeeId' è stata rimossa dalla tabella. Quindi rinomineremo la nuova colonna appena aggiunta 'EmployeeId_new' con 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN'

  6. Per riorganizzare la tabella nella stessa forma in cui era, è necessario aggiungere un vincolo di chiave primaria per la colonna 'EmployeeId'
    ALTER TABLE Chiave primaria aggiunta di Employee [PK_dbo.Employee] (EmployeeId)

8. Ora la tabella "Employee" con "EmployeeId" viene modificata per le regole Identity insieme al vincolo chiave primaria esistente


3

In base alla progettazione, non esiste un modo semplice per attivare o disattivare la funzionalità di identità per una colonna esistente. L'unico modo pulito per farlo è creare una nuova colonna e renderla una colonna di identità o creare una nuova tabella e migrare i dati.

Se utilizziamo SQL Server Management Studio per eliminare il valore dell'identità nella colonna "id", viene creata una nuova tabella temporanea, i dati vengono spostati nella tabella temporanea, la vecchia tabella viene eliminata e la nuova tabella viene rinominata.

Utilizzare Management Studio per apportare la modifica, quindi fare clic con il pulsante destro del mouse nella finestra di progettazione e selezionare "Genera script di modifica".

Vedrai che questo è ciò che SQL Server sta facendo in background.


2

Non ce n'è uno, purtroppo; la proprietà IDENTITY appartiene alla tabella anziché alla colonna.

Il modo più semplice è farlo nella GUI, ma se questa non è un'opzione, puoi fare molto per copiare i dati, rilasciare la colonna, aggiungerli nuovamente con identità e reinserire i dati.

Vedi qui per un account colpo per colpo.


2

Fare clic con il tasto destro sul nome della tabella in Esplora oggetti. Avrai alcune opzioni. Fai clic su "Design". Verrà aperta una nuova scheda per questa tabella. Puoi aggiungere il vincolo di identità qui in "Proprietà colonna".


2

Per modificare le proprietà dell'identità per una colonna:

  • In Esplora server, fare clic con il pulsante destro del mouse sulla tabella con le proprietà dell'identità che si desidera modificare e fare clic su Apri definizione tabella. La tabella si apre in Progettazione tabelle.
  • Deseleziona la casella di controllo Consenti null per la colonna che desideri modificare.
  • Nella scheda Proprietà colonna, espandere la proprietà Specifica identità.
  • Fare clic sulla cella della griglia per la proprietà figlio Is Identity e selezionare Sì dall'elenco a discesa.
  • Digitare un valore nella cella Semenza identità. Questo valore verrà assegnato alla prima riga della tabella. Il valore 1 verrà assegnato per impostazione predefinita.

Ecco fatto, e ha funzionato per me


2

Se ti capita di usare Visual Studio 2017+

  1. In Server Object Explorer fai clic con il pulsante destro del mouse sulla tabella e seleziona "visualizza codice"
  2. Aggiungi il modificatore "IDENTITÀ" alla tua colonna
  3. Aggiornare

Questo farà tutto per te.


Sì! Grazie per aver suggerito questo! Non ho una versione di SSMS sul mio box di Windows 7 che mi consente di apportare modifiche di progettazione alle tabelle sul mio server di produzione perché è il 2017, il mio SSMS è il 2014 e il SSMS del 2017 ha bisogno di Windows 10. Hai reso il mio giorno. È entrato in VS 2017> Esplora server> ha effettuato una nuova connessione a SQL Server di produzione> fai clic con il tasto destro del mouse sulla tabella> "Apri definizione tabella"> Wala!
JustJohn,

In realtà, ho scoperto che puoi fare clic con il pulsante destro del mouse sul campo e selezionare Proprietà e fare l'identità lì scegliendo Sì o No.
JustJohn,

1

Se il poster originale voleva davvero impostare una colonna esistente come a PRIMARY KEYper la tabella e in realtà non aveva bisogno che la colonna fosse una IDENTITYcolonna (due cose diverse), questo può essere fatto tramite t-SQL con:

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

Notare la parentesi attorno al nome della colonna dopo l' PRIMARY KEYopzione.

Anche se questo post è vecchio e sto facendo un'ipotesi sulle esigenze dei richiedenti, ho ritenuto che queste informazioni aggiuntive potrebbero essere utili per gli utenti che incontrano questo thread in quanto credo che la conversazione potrebbe indurre a credere che una colonna esistente non possa essere impostata come chiave primaria senza aggiungerla prima come nuova colonna che sarebbe errata.


1

Come per le mie condizioni attuali, seguo questo approccio. Voglio dare identità a una tabella primaria dopo i dati inseriti tramite script.

Come voglio aggiungere l'identità, quindi inizia sempre da 1 a fine del conteggio dei record che voglio.

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

Ciò creerà la stessa colonna chiave primaria con identità

Ho usato questo link: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Aggiungi la chiave primaria alla tabella esistente


0

Non credo che tu possa modificare una colonna esistente per essere una colonna identità usando tsql. Tuttavia, è possibile farlo tramite la vista di progettazione di Enterprise Manager.

In alternativa, puoi creare una nuova riga come colonna identità, eliminare la colonna precedente, quindi rinominare la nuova colonna.

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

2
tieni presente che se lo fai tramite SSMS / Enterprise Manager, creerai una nuova tabella, copiando i dati, rilasciando la vecchia tabella e rinominando quella nuova. Questo può essere piuttosto costoso quando hai grandi tavoli ...
Scott Ivey,

0

Fondamentalmente ci sono quattro passaggi logici.

  1. Crea una nuova colonna Identità. Attiva Inserisci identità per questa nuova colonna.

  2. Inserisci i dati dalla colonna di origine (la colonna che desideri convertire in Identità) in questa nuova colonna.

  3. Disattiva Inserisci identità per la nuova colonna.

  4. Rilascia la colonna di origine e rinomina la nuova colonna con il nome della colonna di origine.

Potrebbero esserci altre complessità come lavorare su più server ecc.

Per i passaggi fare riferimento al seguente articolo (usando ssms e T-sql). Questi passaggi sono destinati ai principianti con meno grip su 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 uno script per tutte le tabelle con chiave primaria = bigint che non hanno un set di identità; questo restituirà un elenco di script generati con ogni tabella;

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.