PRIMO
Probabilmente non c'è bisogno tutte le tre colonne: old_id
, external_id
, new_id
. La new_id
colonna, essendo un IDENTITY
, avrà un nuovo valore generato per ogni riga, anche quando si inserisce in external_id
. Ma tra old_id
e external_id
, quelli si escludono a vicenda: o c'è già un old_id
valore o quella colonna, nella concezione attuale, sarà solo NULL
se si usa external_id
o new_id
. Dal momento che non aggiungerai un nuovo ID "esterno" a una riga già esistente (ovvero uno che ha un old_id
valore) e non ci saranno nuovi valori in arrivo old_id
, quindi può esserci una colonna che viene utilizzata per entrambi gli scopi.
Quindi, sbarazzati della external_id
colonna e rinomina old_id
per essere qualcosa del genere old_or_external_id
o qualunque cosa. Ciò non dovrebbe richiedere cambiamenti reali a nulla, ma riduce alcune delle complicazioni. Al massimo potresti dover chiamare la colonna external_id
, anche se contiene valori "vecchi", se il codice dell'app è già scritto per essere inserito external_id
.
Ciò riduce la nuova struttura in modo che sia:
PkId AS AS COALESCE(old_or_external_id, new_id, -1) PERSISTED NOT NULL,
old_or_external_id INT NULL, -- values from existing record OR passed in from app
new_id INT IDENTITY(2000000, 1) NOT NULL
Ora hai aggiunto solo 8 byte per riga anziché 12 byte (supponendo che tu non stia utilizzando l' SPARSE
opzione Compressione dati). E non è stato necessario modificare alcun codice, T-SQL o codice app.
SECONDO
Continuando lungo questo percorso di semplificazione, diamo un'occhiata a ciò che ci è rimasto:
- La
old_or_external_id
colonna ha già dei valori o verrà assegnato un nuovo valore dall'app o verrà lasciato come NULL
.
- Il
new_id
avranno sempre un nuovo valore generato, ma tale valore verrà utilizzato solo se la old_or_external_id
colonna è NULL
.
Non c'è mai un momento in cui avresti bisogno di valori in entrambi old_or_external_id
e new_id
. Sì, ci saranno momenti in cui entrambe le colonne hanno valori dovuti a new_id
essere un IDENTITY
, ma tali new_id
valori vengono ignorati. Ancora una volta, questi due campi si escludono a vicenda. Così quello che ora?
Ora possiamo capire perché avevamo bisogno external_id
del primo. Considerando che è possibile inserire in una IDENTITY
colonna utilizzando SET IDENTITY_INSERT {table_name} ON;
, è possibile evitare di apportare modifiche allo schema e modificare solo il codice dell'app per avvolgere le INSERT
dichiarazioni / operazioni SET IDENTITY_INSERT {table_name} ON;
e le SET IDENTITY_INSERT {table_name} OFF;
istruzioni. È quindi necessario determinare su quale intervallo iniziale reimpostare la IDENTITY
colonna (per i valori appena generati) in quanto dovrà essere ben al di sopra dei valori che il codice dell'app inserirà poiché l'inserimento di un valore più elevato comporterà il successivo valore generato automaticamente essere maggiore dell'attuale valore MAX. Ma puoi sempre inserire un valore inferiore al valore IDENT_CURRENT .
La combinazione delle colonne old_or_external_id
e new_id
non aumenta inoltre le possibilità di imbattersi in una situazione di valori sovrapposti tra valori generati automaticamente e valori generati dall'app poiché l'intenzione di avere le colonne 2 o anche 3 è combinarle in un valore Chiave primaria, e quelli sono sempre valori unici.
In questo approccio, devi solo:
Lasciare le tabelle come:
PkId INT IDENTITY(1,1) PRIMARY KEY
Ciò aggiunge 0 byte a ogni riga, anziché 8 o anche 12.
- Determina l'intervallo iniziale per i valori generati dall'app. Questi saranno maggiori del valore MAX corrente in ciascuna tabella, ma inferiore a quello che diventerà il valore minimo per i valori generati automaticamente.
- Determinare da quale valore deve iniziare l'intervallo generato automaticamente. Dovrebbe esserci molto spazio tra l'attuale valore MAX e molto spazio per crescere, sapendo che il limite superiore è di poco superiore a 2,14 miliardi. È quindi possibile impostare questo nuovo valore seed minimo tramite DBCC CHECKIDENT .
- Inserisci il codice dell'app INSERISCI
SET IDENTITY_INSERT {table_name} ON;
e le SET IDENTITY_INSERT {table_name} OFF;
istruzioni.
SECONDO, Parte B
Una variante del metodo indicato direttamente sopra sarebbe avere il codice App inserto valori iniziano -1 e andando giù di lì. Questo lascia i IDENTITY
valori come gli unici che salgono . Il vantaggio qui è che non solo non complicate lo schema, ma non dovete nemmeno preoccuparvi di imbattervi in ID sovrapposti (se i valori generati dall'app vengono eseguiti nel nuovo intervallo generato automaticamente). Questa è un'opzione solo se non stai già utilizzando valori ID negativi (e sembra piuttosto raro che le persone utilizzino valori negativi su colonne generate automaticamente, quindi questa dovrebbe essere una probabile posibilità nella maggior parte delle situazioni).
In questo approccio, devi solo:
Lasciare le tabelle come:
PkId INT IDENTITY(1,1) PRIMARY KEY
Ciò aggiunge 0 byte a ogni riga, anziché 8 o anche 12.
- L'intervallo iniziale per i valori generati dall'app sarà
-1
.
- Inserisci il codice dell'app INSERISCI
SET IDENTITY_INSERT {table_name} ON;
e le SET IDENTITY_INSERT {table_name} OFF;
istruzioni.
Qui devi ancora fare il IDENTITY_INSERT
, ma: non aggiungi nuove colonne, non devi "ridimensionare" nessuna IDENTITY
colonna e non hai rischi futuri di sovrapposizioni.
SECONDO, Parte 3
Un'ultima variante di questo approccio potrebbe essere quella di scambiare le IDENTITY
colonne e utilizzare invece le sequenze . Il motivo per adottare questo approccio è di poter inserire nel codice dell'app valori che sono: positivi, al di sopra dell'intervallo generato automaticamente (non al di sotto) e non è necessario SET IDENTITY_INSERT ON / OFF
.
In questo approccio, devi solo:
- Crea sequenze usando CREATE SEQUENCE
Copia la IDENTITY
colonna in una nuova colonna che non ha la IDENTITY
proprietà, ma ha un DEFAULT
vincolo che utilizza la funzione PROSSIMO VALORE PER :
PkId INT PRIMARY KEY CONSTRAINT [DF_TableName_NextID] DEFAULT (NEXT VALUE FOR...)
Ciò aggiunge 0 byte a ogni riga, anziché 8 o anche 12.
- L'intervallo iniziale per i valori generati dall'app sarà ben al di sopra di quello che pensi si avvicinino ai valori generati automaticamente.
- Inserisci il codice dell'app INSERISCI
SET IDENTITY_INSERT {table_name} ON;
e le SET IDENTITY_INSERT {table_name} OFF;
istruzioni.
TUTTAVIA , a causa della necessità che il codice con una SCOPE_IDENTITY()
o @@IDENTITY
funzioni ancora correttamente, il passaggio a Sequenze non è attualmente un'opzione in quanto sembra che non ci siano equivalenti di tali funzioni per Sequenze :-(. Triste!