Contadores con gestión de huecos

Escrito por qwalgrande 29-05-2011 en General. Comentarios (1)

 

Hace unos meses publiqué un hilo en que se exponía cómo obtener un contador sin hacer uso de un identity.

 

Vamos ahora a ampliar un poco uno de esos mecanismos para añadirle una gestión de huecos. La idea consiste en contar con un procedimiento almacenado que dé de alta los huecos cuando estos se produzcan (por el motivo que sea). Y luego, en el procedimiento del contador, consumir esos huecos si existen. Este sería el procedimiento para el alta de huecos, el de obtención del contador que usa huecos y las tablas implicadas. Al final se incluyen unos ejemplos de llamada.

 

 

CREATE TABLE [dbo].[CONTADORES](

                [ID] [smallint] IDENTITY(1,1) NOT NULL,

                [DES_TABLA] [varchar](255) NOT NULL,

                [NUM_ID] [int] NOT NULL,

 CONSTRAINT [PK_CONTADORES] PRIMARY KEY CLUSTERED

(

                [ID] ASC

))

 

GO

 

CREATE TABLE [dbo].[CONTADORES_HUECOS](

                [ID] [smallint] IDENTITY(1,1) NOT NULL,

                [DES_TABLA] [varchar](255) NOT NULL,

                [NUM_ID] [int] NOT NULL,

                [IND_ESTADO]  [bit] NOT NULL default (1),

 CONSTRAINT [PK_CONTADORES_HUECOS] PRIMARY KEY CLUSTERED

(

                [ID] ASC

))

 

GO

CREATE NONCLUSTERED INDEX [IX_CONTADORES_HUECOS_A1] ON [dbo].[CONTADORES_HUECOS]([DES_TABLA], [IND_ESTADO])

GO

 

--Para los huecos

CREATE proc [dbo].[p_NuevoHueco]

                @pTable_Name varchar(255),

                @pId int as

set nocount on

 

declare @ret int

 

insert CONTADORES_HUECOS (DES_Tabla, NUM_Id) values (@pTable_Name, @pId)

--Control de errores

select @ret = @@error

if @ret <> 0 

 begin 

  raiserror('Error en la inserción del hueco.', 1, 16) 

  set nocount off 

  return @ret 

 end 

 

set nocount off

return 0

GO

 

--Para obtener los identificadores

CREATE proc [dbo].p_GetID

                @pTable_Name varchar(255),

                @pNewId int OUTPUT as 

set nocount on 

 

declare @ret int

 

--Se intenta obtener un hueco, en caso de que exista

if exists(select DES_Tabla from CONTADORES_HUECOS where DES_Tabla = @pTable_Name)

                begin

                               set rowcount 1

                               --Se reserva el hueco a la vez que se toma el ID

                               update CONTADORES_HUECOS set @pNewId = NUM_ID, IND_Estado = 0                            

                               where DES_Tabla = @pTable_Name and IND_Estado = 1

                               set rowcount 0

                               --En caso de que no se capture un id porque otro proc lo haya pillado desde que se hizo la comprobación hasta que se lanza el update,

                               --se llama recursivamente al proc de obtención de id, se llama al propio procedimiento almacenado.

                               if @pNewId is null

                                               begin

                                                               exec @ret = pau_CON_CONTADORES_GetId @pTable_Name, @pNewId OUTPUT

                                                               return @ret

                                               end

                               else

                                               begin

                                                               delete CONTADORES_HUECOS

                                                               where DES_Tabla = @pTable_Name and NUM_ID = @pNewId

                                               end

                end

--Se consulta si el contador para la tabla  ya existe en Contadores 

else if exists(select DES_Tabla from Contadores where DES_Tabla = @pTable_Name) 

 begin --Si ya existe, se obtiene el siguiente valor del contador. 

  update Contadores set @pNewID = NUM_ID = NUM_ID + 1 

  from Contadores 

  where

                               DES_Tabla = @pTable_Name

 end 

else 

 begin --Si no existe, se inserta el nuevo valor 

  select @pNewID = 1 

  insert Contadores (DES_Tabla, NUM_ID)

                values (@pTable_Name, @pNewID)   

 end 

 

--Control de errores 

select @ret = @@error 

if @ret <> 0 

 begin 

  raiserror('Error en la obtención de nuevo identificador', 1, 16) 

  set nocount off 

  return @ret 

 end 

 

set nocount off 

return 0

 

 

 

GO

 

 

--Ejecuciones:

DECLARE @RC int, @NuevoId int

EXEC @RC = dbo.p_GetID @pTable_Name = 'RECIBOS'  ,@pNewId = @NuevoId OUTPUT

select @RC as Resultado, @NuevoId as Identificador

go

select * from Contadores

go

--Insertamos un hueco, por ejemplo el 2, por un borrado en la tabla que usa el contador

EXEC dbo.[p_NuevoHueco] @pTable_Name = 'RECIBOS'  ,@pId = 2

 

GO

 

--Consumimos el hueco

DECLARE @RC int, @NuevoId int

EXEC @RC = dbo.p_GetID @pTable_Name = 'RECIBOS'  ,@pNewId = @NuevoId OUTPUT

select @RC as Resultado, @NuevoId as Identificador

go

select * from Contadores