Mailson, this is one of several problems when using IDENTITY or SEQUENCE.
Some tables use a substitute key as a primary key, rather than a natural key. Generally this substitute key is a numerical value, sequential and increasing. In some applications there can be no jump in the generation of this sequence. Something that seems simple becomes complicated when considering the occurrence of simultaneous transactions in the same tables and objects. The solution is the creation of own mechanism to generate sequential values for key.
In the article Generation of numerical sequences is the "Sequence Table" method, where an auxiliary table is used to store the last value generated in the sequence. The implementation in stored procedure of obtaining the next value of the sequence simplifies the process. Multiple sequencers can be stored in the same table for different uses.
The use of the stored procedure can be to insert a single row or else to a block of rows. For a single line we can have something like:
-- código #2.15
-- próximo valor disponível
declare @Prox_Valor int;
BEGIN TRANSACTION;
EXECUTE dbo.GetSequence
@nome_seq= 'dbo.Pessoa.ID_Pessoa',
@valor = @Prox_Valor output;
INSERT into dbo.Pessoa (ID_Pessoa, Nome_Pessoa)
values (@Prox_Valor, 'Paulo Antunes');
COMMIT;
go
The transaction is defined explicitly, being composed of the call to the stored procedure that gets the next key and the inclusion command of the line. In this method the next value generation of the sequence is within the same transaction block of the INSERT command; this is to ensure that there are no holes in the generated sequence.
The details are in the article "Generation of numerical sequences"from which I extracted excerpts for this answer.
Creation of the auxiliary table:
-- código #2.12 v2
USE banco;
go
IF OBJECT_ID ('dbo.tbSequence', 'U') is not null
DROP TABLE dbo.tbSequence;
CREATE TABLE dbo.tbSequence (
Seq varchar(30) not null unique,
Valor int not null default 0
);
go
Creation of the stored procedure generating the sequence:
-- código #2.13 v2
IF OBJECT_ID ('dbo.GetSequence') is not null
DROP PROCEDURE dbo.GetSequence;
go
CREATE PROCEDURE dbo.GetSequence
@nome_seq varchar(30),
@valor int output,
@n int = 1
as
begin
set nocount on;
declare @retorno int, @NLinhas int;
set @valor= NULL;
UPDATE dbo.tbSequence
set @valor = Valor = Valor + @n
where Seq = @nome_seq;
SELECT @retorno= @@error, @NLinhas= @@rowcount;
IF @retorno = 0
begin
IF @NLinhas = 1
set @valor= @valor - @n +1
else
set @retorno= -1; -- erro na geração do próximo valor
end;
return @retorno;
end;
go
Read the "Sequence table" method in the article Generation of numerical sequences. -> https://portosql.wordpress.com/artigos/
– José Diz