Autonumérico entre varias tablas

Tenemos dos tablas de datos en SQL Server en las cuales se van a insertar filas indiscriminadamente. Necesitamos saber en qué orden fueron insertadas estas filas, poder sacar un UNION entre ambas tablas y ordenarla por su inserción. Es necesario además detectar ‘huecos’ en las filas, es decir, queremos crear un autonumérico pero que implique a ambas tablas.

Cómo sabemos, si utlizamos un campo integer la numeración es independiente en cada una de las tablas implicadas, así que no nos sirve. Un timestamp tampoco es la solución, ya que varía con cada versión de la fila: cada update que hagamos sobre la fila actualizará a su vez la columna timestamp.

La otra solución sería utilizar como clave un campo fecha, lo cual nos solucionaría el problema de unir las dos tablas pero no el de la detección de huecos. No habría forma a saber si entre dos filas de la tabla A hay alguna de la tabla B a no ser que hagamos la union directamente.

Desde 2005 tenemos una solución a este problema: newsequentialId(). Esta función sólo se puede utilizar como Default Constraint y nos devuelve un GUID distinto de cada vez, pero de forma secuencial.

En la imagen superior podemos ver el resultado de realizar dos inserciones en la tabla A, una en la B, y a continuación seguir insertando en la A. El byte menos significativo del GUID está representado por los dos primeros caracteres hexadecimales. Cómo se puede ver, son secuenciales E7, E8, falta el E9 y continua con EA, EB… La serie es muy sencilla de predecir: ECD0, EDD0, EED0, EFD0, F0D0, F1D0, …, FFD0, 00D1, 01D1 ,…

Objetivo cumplido: orden, unicidad y densidad! El código de prueba para generar las tablas de ejemplo es el siguiente:

create table #TablaA
(
  
IdNum int identity(1,1),
  
IdGuid uniqueidentifier default(NEWSEQUENTIALID()),
  
valor varchar(50)
);

create table #TablaB
(
   IdNum int identity(1,1),
  
IdGuid uniqueidentifier default(NEWSEQUENTIALID()),
  
valor varchar(50)
);

insert into #TablaA(valor)values (‘a’)
insert into #TablaA(valor)values (‘a’)
insert into #TablaB(valor)values (‘a’)
insert into #TablaA(valor)values (‘a’)
insert into #TablaA(valor)values (‘a’)

select * from #TablaA
select * from #TablaB