Quante volte è capitato di voler "riempire i buchi" lasciati da un campo contatore? In effetti, una volta definito un identity, non dovremmo preoccuparci di una problematica di questo tipo, però può accadere di avere un campo numerico che non deve assolutamente lasciare "buchi".. Potrebbero esistere campi gestiti come progressivi i quali, dopo varie cancellazioni fisiche, lasciano spazi nel conteggio.
Ecco, in quei casi è utile ricavare il primo spazio in cui inserire il nostro contatore/progressivo applicativo..
Scenario:
Ho una tabella di anagrafica della mia azienda (alcuni dipendenti ) e ho la necessità di inserire i nuovi dipendenti nel primo "buco" lasciato libero dai licenziamenti di dipendenti precedenti. Quindi, devo fornire qualcosa che mi dica quale spazio posso riempire:
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id('TabellaContatori'))
DROP TABLE TabellaContatori
-- creo la tabella con un campo intero che sarà il nostro contatore applicativo
---------------------------------------------------------------------------------
CREATE TABLE TabellaContatori
(
Id int NOT NULL,
Nome varchar(30) NOT NULL,
Cognome varchar(30) NOT NULL,
Eta tinyint NOT NULL,
CONSTRAINT PK_TabellaContatori PRIMARY KEY CLUSTERED
(
Id
)
)
-- inserisco nella tabella alcuni record con contatori non seguenti
---------------------------------------------------------------------------------
INSERT INTO TabellaContatori
SELECT 1,'Alessandro','Alpi', 25
INSERT INTO TabellaContatori
SELECT 2,'Alex','Rabboni', 23
INSERT INTO TabellaContatori
SELECT 5,'Marco','Rossi', 25
INSERT INTO TabellaContatori
SELECT 6,'Michael','Denny', 23
INSERT INTO TabellaContatori
SELECT 8,'Matteo','Celaschi', 28
INSERT INTO TabellaContatori
SELECT 9,'Davide','Manuto', 24
---------------------------------------------------------------------------------
-- Ricavo il primo contatore seguente e lo inserisco (ovviamente il tutto si può
-- strutturare con variabili e transazioni)
---------------------------------------------------------------------------------
SELECT
TOP 1 IdDaInserire = TC1.Id + 1
FROM
TabellaContatori TC1
LEFT JOIN
TabellaContatori TC2
ON TC2.id = TC1.Id + 1
WHERE
TC2.id IS NULL
INSERT INTO TabellaContatori
SELECT 3,'Daniele','Zanella', 32
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
SELECT
TOP 1 IdDaInserire = TC1.Id + 1
FROM
TabellaContatori TC1
LEFT JOIN
TabellaContatori TC2
ON TC2.id = TC1.Id + 1
WHERE
TC2.id IS NULL
INSERT INTO TabellaContatori
SELECT 4,'Massimo','Preitano', 44
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
SELECT
TOP 1 IdDaInserire = TC1.Id + 1
FROM
TabellaContatori TC1
LEFT JOIN
TabellaContatori TC2
ON TC2.id = TC1.Id + 1
WHERE
TC2.id IS NULL
INSERT INTO TabellaContatori
SELECT 7,'Luca','Ferrari', 26
Come già indico in un commento interno è possibile ottimizzare l'utilizzo di questo codice tramite l'utilizzo di transazioni e di variabili, in modo da crearsi una stored procedure che in automatico inserisce i dati nella prima "locazione" disponibile, con la possibilità di gestione delle contention e dei vari errori.
Oppure è possibile farsi una User Function, che ritorna solo il primo spazio libero..
Insomma, tutto questo lo lascio a voi
Stay tuned!