PRIMO
Probabilmente non c'è bisogno tutte le tre colonne: old_id, external_id, new_id. La new_idcolonna, essendo un IDENTITY, avrà un nuovo valore generato per ogni riga, anche quando si inserisce in external_id. Ma tra old_ide external_id, quelli si escludono a vicenda: o c'è già un old_idvalore o quella colonna, nella concezione attuale, sarà solo NULLse si usa external_ido new_id. Dal momento che non aggiungerai un nuovo ID "esterno" a una riga già esistente (ovvero uno che ha un old_idvalore) 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_idcolonna e rinomina old_idper essere qualcosa del genere old_or_external_ido 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' SPARSEopzione 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_idcolonna ha già dei valori o verrà assegnato un nuovo valore dall'app o verrà lasciato come NULL.
- Il
new_idavranno sempre un nuovo valore generato, ma tale valore verrà utilizzato solo se la old_or_external_idcolonna è NULL.
Non c'è mai un momento in cui avresti bisogno di valori in entrambi old_or_external_ide new_id. Sì, ci saranno momenti in cui entrambe le colonne hanno valori dovuti a new_idessere un IDENTITY, ma tali new_idvalori vengono ignorati. Ancora una volta, questi due campi si escludono a vicenda. Così quello che ora?
Ora possiamo capire perché avevamo bisogno external_iddel primo. Considerando che è possibile inserire in una IDENTITYcolonna utilizzando SET IDENTITY_INSERT {table_name} ON;, è possibile evitare di apportare modifiche allo schema e modificare solo il codice dell'app per avvolgere le INSERTdichiarazioni / 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 IDENTITYcolonna (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_ide new_idnon 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 IDENTITYvalori 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 IDENTITYcolonna e non hai rischi futuri di sovrapposizioni.
SECONDO, Parte 3
Un'ultima variante di questo approccio potrebbe essere quella di scambiare le IDENTITYcolonne 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 IDENTITYcolonna in una nuova colonna che non ha la IDENTITYproprietà, ma ha un DEFAULTvincolo 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 @@IDENTITYfunzioni ancora correttamente, il passaggio a Sequenze non è attualmente un'opzione in quanto sembra che non ci siano equivalenti di tali funzioni per Sequenze :-(. Triste!