¿Dónde almacena SQL Server físicamente el VALOR DE IDENTIDAD para una tabla?

12

Espero que alguien pueda señalarme en la dirección correcta en este caso. Aquí está mi trabajo hasta ahora.

SELECT * FROM sys.identity_columnses una vista del sistema que proporciona "last_value", pero la definición de esa vista usa una función interna IdentityProperty(colName, 'LastValue'), por lo que es un callejón sin salida (no extraerlo de una tabla del sistema allí).

En todas partes (he buscado) en Internet sugiere usar DBCC IDENT_...comandos para descubrir el valor, pero eso todavía me deja en la oscuridad en cuanto a dónde está realmente almacenado.

Entonces, llegué a buscar en las páginas individuales con DBCC PAGE(TestDB,1,1325,3)mi arnés de prueba db y utilicé el RESEEDcomando para reiniciar entre los valores 10 y 12.

Al hacer esto, noté los valores hexadecimales en el IAM: Header, IAM: Single Page Allocationsy IAM: Extent Alloc Status Slot 1todo cambió. (Y se dio cuenta de que cambian periódicamente de todos modos junto con el valor bUse1 que también cambia gradualmente por sí mismo).

Así que otro callejón sin salida y estoy sin ideas ¿Dónde más puedo buscar?

Estoy ejecutando SQL Server 2014. Tengo una sed insaciable por el conocimiento interno y aún no he encontrado nada tan difícil como esto. Me llamó la atención porque, en teoría, (un valor absoluto) se almacena en algún lugar y debería (posiblemente) ser localizable. En mi búsqueda para descubrir ubicaciones de datos / metadatos almacenados internamente, este valor particular me parece particularmente difícil de alcanzar. Supongo / espero que alguien venga y me diga, puedes hacerlo, DBCC PAGEpero estaba buscando en el lugar equivocado.

Simon Jones
fuente

Respuestas:

8

Si puede acceder a la DAC ( Consola de administrador dedicada ), puede inspeccionar el valor de la columna de identidad, para INTcolumnas, mirando la idtvalcolumna en sys.syscolpars.

Gracias a Martin Smith por dirigirme a esa mesa a través de esta respuesta muy útil de Roi Gavish sobre una pregunta relacionada aquí.

Tomemos, por ejemplo, la siguiente tabla temporal:

USE tempdb;

CREATE TABLE #d
(
    ID INT NOT NULL IDENTITY(1,1)
);

TRUNCATE TABLE #d;

DBCC CHECKIDENT ('#d',RESEED, 2147483635);

INSERT INTO #d DEFAULT VALUES;

Veamos qué contiene la tabla:

SELECT *
FROM #d;
+------------+
| ID         |
+------------+
| 2147483635 |
+------------+

El valor de identidad puede ser inspeccionado por este código:

DECLARE @idtval VARBINARY(64);

SELECT @idtval = scp.idtval
FROM sys.syscolpars scp
    INNER JOIN sys.objects o ON scp.id = o.object_id
WHERE o.name LIKE '#d____%'

DECLARE @LittleEndian NVARCHAR(10);
SET @LittleEndian = LEFT(sys.fn_varbintohexstr(@idtval), 10);
SELECT @LittleEndian;
DECLARE @BigEndian NVARCHAR(10) = '0x';
DECLARE @Loop INT = 0;
WHILE @Loop < 4
BEGIN
  SET @BigEndian = @BigEndian + SUBSTRING(@LittleEndian, ((4 - @Loop) * 2) + 1, 2);
  SET @Loop += 1;
END
SELECT CurrentIdentityValue = CONVERT(INT, 
    CONVERT(VARBINARY(32), @BigEndian, 1), 2);
+----------------------+
| CurrentIdentityValue |
+----------------------+
|                      |
| 2147483635           |
+----------------------+

Para BIGINTlas columnas de identidad, necesitamos expandir el tamaño de algunas variables utilizadas en el código, como:

CREATE TABLE #dBig
(
    ID BIGINT NOT NULL IDENTITY(1,1)
);

TRUNCATE TABLE #dBig;

DBCC CHECKIDENT ('#dBig',RESEED, 9223372036854775704);

INSERT INTO #dBig DEFAULT VALUES;

SELECT *
FROM #dBig;


DECLARE @idtval VARBINARY(64);

SELECT @idtval = scp.idtval
FROM sys.syscolpars scp
    INNER JOIN sys.objects o ON scp.id = o.object_id
WHERE o.name LIKE '#dBig____%'

DECLARE @LittleEndian NVARCHAR(18);
SET @LittleEndian = LEFT(sys.fn_varbintohexstr(@idtval), 18);
DECLARE @BigEndian NVARCHAR(18) = '0x';
DECLARE @Loop INT = 0;
WHILE @Loop < 8
BEGIN
  SET @BigEndian = @BigEndian + SUBSTRING(@LittleEndian, ((8 - @Loop) * 2) + 1, 2);
  SET @Loop += 1;
END
SELECT CurrentIdentityValue = CONVERT(BIGINT, 
    CONVERT(VARBINARY(32), @BigEndian, 1), 2);

Resultados para BIGINT:

+----------------------+
| CurrentIdentityValue |
+----------------------+
|                      |
| 9223372036854775704  |
+----------------------+
Max Vernon
fuente