Onde o SQL Server armazena fisicamente o IDENTITY VALUE para uma tabela?

12

Espero que alguém possa me indicar a direção certa. Aqui está o meu trabalho até agora.

SELECT * FROM sys.identity_columnsé uma visão do sistema que fornece "last_value", mas a definição para essa visão usa uma função interna IdentityProperty(colName, 'LastValue')- portanto, esse é um beco sem saída (não é retirado da tabela do sistema).

Em todos os lugares (já olhei) na internet, sugerimos o uso de DBCC IDENT_...comandos para descobrir o valor, mas isso ainda me deixa no escuro sobre onde ele está realmente armazenado.

Portanto, cheguei a pesquisar nas páginas individuais com o DBCC PAGE(TestDB,1,1325,3)meu equipamento de teste db e usando o RESEEDcomando para reenviar entre os valores 10 e 12.

Ao fazer isso, eu observei os valores hexadecimais na IAM: Header, IAM: Single Page Allocationse IAM: Extent Alloc Status Slot 1tudo mudou. (E perceberam que eles mudam periodicamente de qualquer maneira, juntamente com o valor bUse1, que também é incrementado por si só).

Então, outro beco sem saída e estou sem idéias. Onde mais posso pesquisar?

Estou executando o SQL Server 2014. Tenho uma sede insaciável de conhecimento interno e ainda preciso encontrar algo tão esquivo quanto isso. Isso chamou minha atenção porque, em teoria, ele (um valor absoluto) é armazenado em algum lugar e deve (sem dúvida) ser localizável. Na minha busca por descobrir locais de dados / metadados armazenados internamente, esse valor em particular me parece particularmente ilusório. Eu estou supondo / esperando que alguém venha e me diga, você pode entender, DBCC PAGEmas eu estava procurando no lugar errado.

Simon Jones
fonte

Respostas:

8

Se você puder acessar o DAC ( Dedicated Administrator Console ), poderá inspecionar o valor da coluna de identidade, para INTcolunas, observando a idtvalcoluna em sys.syscolpars.

Agradeço a Martin Smith por me direcionar para essa mesa por meio desta resposta muito útil de Roi Gavish sobre uma questão relacionada aqui.

Tome, por exemplo, a seguinte tabela temporária:

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;

Vamos ver o que a tabela contém:

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

O valor da identidade pode ser inspecionado 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 BIGINTcolunas de identidade, precisamos expandir o tamanho de algumas variáveis ​​usadas no 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
fonte