Perché la rimozione della proprietà Identity su una colonna non è supportata


11

Ho letto che dopo SQL Server 2000 è stata rimossa la possibilità di "annullare l'identità" di una colonna di identità. E che questa era "In base alla progettazione" (non solo una caratteristica mancante).

Ecco un esempio che ho trovato su un blog . Implica l'aggiornamento delle tabelle di sistema. (E questa capacità è stata rimossa dopo SQL Server 2000.) Capisco che farlo tramite le tabelle di sistema non sia una buona idea. Mi sto solo chiedendo perché una funzione per farlo in un altro modo non sia presente.

Lavorare intorno a questo mi farà lavorare molto. (Copia di centinaia di milioni di righe su nuove tabelle in un ambiente intollerante ai tempi di inattività.)

Quindi ho pensato di chiedere "Perché".

Che cosa è cambiato in SQL Server 2005 e nelle versioni successive che lo hanno reso negativo? O è sempre stato male, e semplicemente non bloccato?

Quale "Best Practice" (o principio simile) verrebbe violato trasformando nuovamente una colonna di identità in una colonna normale?

-

Aggiornamento per rispondere alla richiesta di "perché lo sto facendo":
questo è un riepilogo di altissimo livello: inizierò ad aggiungere partizioni alle mie tabelle. (In modo che io possa archiviare / eliminare i vecchi dati.) È tutto facile. Ma ogni tanto ho bisogno di spostare un record in una diversa partizione in modo che non venga rimosso (quando viene visualizzata una partizione per l'archiviazione / eliminazione). (Sto avendo la mia colonna di partizionamento aumentare di 2 in modo che ci sia sempre spazio per spostare la riga in una diversa partizione.)

Ma se la colonna di partizionamento è una colonna di identità, allora devo eliminare e reinserire il valore (non c'è modo di aggiornare il valore di una colonna di identità). Che causa problemi con la replica.

Quindi voglio usare una sequenza invece di una colonna identità. Ma questo passaggio è molto difficile su database di grandi dimensioni.

Risposte:


22

La tua domanda è, essenzialmente:

Perché non posso più fare questa cosa rischiosa che in primo luogo non avrei mai dovuto fare?

La risposta a questa domanda è in gran parte irrilevante (anche se puoi vedere alcuni commenti Microsoft in questi elementi di Connect che richiedono questa funzionalità: # 294193 e # 252226). Per completezza, la mia sinossi è: la capacità di rimuovere la proprietà dell'identità è stata un effetto collaterale indesiderato di avere la possibilità di pasticciare con le tabelle di sistema in primo luogo. Questo non doveva essere usato in molti modi, spesso con conseguenze molto negative, e quindi è stato rimosso. Era un hack non documentato, non supportato, da tavolo di sistema. La possibilità di modificare i dati nelle tabelle di sistema non è stata rimossa perché Microsoft non voleva più farti uscire da una colonna come colonna di identità, è stata rimossa perché confondersi con le tabelle di sistema è estremamente rischioso. La rimozione della proprietà IDENTITY in sé non era una rimozione di funzionalità specificamente mirata e non mi sarei mai fidato completamente di questo approccio nemmeno nei tempi antichi in cui era possibile.

Detto questo, che ne dici di rispondere a questa domanda invece?

Come rimuovo la proprietà IDENTITY di una colonna con tempi di inattività minimi o nulli?

Puoi farlo facilmente, usando ALTER TABLE ... SWITCHuna tecnica che sono certo di aver appreso per la prima volta dal nostro Paul White nelle soluzioni alternative per Connect # 252226 . Esempio rapido, data questa semplice tabella:

CREATE TABLE dbo.Original
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  name SYSNAME
);
GO

INSERT dbo.Original(name) VALUES(N'foo'),(N'bar');
GO

SELECT * FROM dbo.Original;
GO

risultati:

ID  name
--  ----
1   foo
2   bar

Ora creiamo una tabella shadow e passiamo ad essa, quindi rilasciamo la tabella precedente, rinominiamo quella nuova e quindi riprendiamo l'attività normale:

CREATE TABLE dbo.New
(
  ID INT PRIMARY KEY,
  name SYSNAME
);
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
  ALTER TABLE dbo.Original SWITCH TO dbo.New;
  DROP TABLE dbo.Original;
  EXEC sys.sp_rename N'dbo.New', N'Original', 'OBJECT';
COMMIT TRANSACTION;
GO

INSERT dbo.Original(ID,name) VALUES(3,N'splunge');
UPDATE dbo.Original SET ID = 6 WHERE ID = 1;
GO

SELECT * FROM dbo.Original;
GO

risultati:

ID  name
--  -------
2   bar
3   splunge
6   foo

Ora ripulisci:

DROP TABLE dbo.Original;

Questa è solo un'operazione di metadati, senza spostamento di dati, e bloccherà solo altri utenti mentre i metadati vengono aggiornati. Ma, è vero, è un esempio molto semplicistico. Se si dispone di chiavi esterne o si utilizzano altre funzionalità come la replica, Change Data Capture, Change Tracking, ecc., Potrebbe essere necessario disabilitarne o rimuoverne alcune prima di apportare questa modifica (non ho testato tutte le combinazioni). Per le chiavi esterne in particolare, vedere questo suggerimento che mostra come generare script per eliminare e ricreare tutti i vincoli di chiave esterna (o selezionati).

Inoltre, sarà necessario aggiornare il codice dell'applicazione per evitare che SQL Server compili questa colonna e controllare eventuali istruzioni di inserimento o selezione che potrebbero dipendere dall'ordine delle colonne o dalle colonne che devono specificare. In generale, desidero greppare l'intera base di codici per qualsiasi menzione di questa tabella.

Vedi anche questo script di Itzik Ben-Gan (fonte: questo antico articolo ) per un altro modo di gestirlo, ma qui è coinvolto lo spostamento dei dati, quindi non fornisce il requisito "nessun o minimo tempo di inattività".


3
Vorrei incoraggiare chiunque venga a votare i due elementi di connessione. Quanto può essere difficile implementare una funzione ALTER COLUMN che attiva o disattiva l'identità booleana ?! Doloroso aggirare.
usr

Devo ammetterlo, per qualche motivo ho pensato che ..SWITCH..funzionasse solo per le tabelle che avevano almeno una partizione definita.
RBarryYoung,

Voglio solo aggiungere che SWITCHnon richiede Enterprise Edition, anche se il partizionamento delle tabelle lo fa.
Dan Guzman,
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.