web-dev-qa-db-fra.com

Où SQL Server stocke physiquement la valeur d'identité pour une table?

J'espère que quelqu'un peut me diriger dans la bonne direction sur celui-ci. Voici mon fonctionnement jusqu'à présent.

SELECT * FROM sys.identity_columns Est une vue système qui donne "last_value", mais la définition de cette vue utilise une fonction interne IdentityProperty(colName, 'LastValue') - C'est donc une impasse (sans le tirant d'une table de système).

Partout (j'ai regardé) sur Internet suggère d'utiliser DBCC IDENT_... Commandes de découvrir la valeur mais qui me laisse toujours dans le noir de l'endroit où elle est réellement stockée.

Donc, je suis arrivé à la recherche des pages individuelles avec DBCC PAGE(TestDB,1,1325,3) contre mon harnais de test DB et à l'aide de la commande RESEED pour réexécuter entre les valeurs 10 et 12.

Ce faisant, j'ai remarqué les valeurs hexagonales sur le IAM: Header, IAM: Single Page Allocations Et IAM: Extent Alloc Status Slot 1 Tout a changé. (Et réalisé qu'ils changent périodiquement de toute façon avec la valeur Buse1 la valeur qui change progressivement par lui-même).

Donc, une autre impasse et je suis tout à fait des idées. Où puis-je rechercher?

Je couronne SQL Server 2014. J'ai une soif insatiable pour la connaissance des internes et je n'ai pas encore rencontré de quoi que ce soit aussi insaisissable que cela. Il a attiré mon attention car en théorie, elle (une valeur absolue) est stockée quelque part et devrait (sans doute) être localisable. Dans ma quête de la découverte des emplacements de données/métadonnées stockées en interne, cette valeur particulière me frappe comme particulièrement insaisissable. Je suppose/espère que quelqu'un va venir et me le dire, vous pouvez l'obtenir avec DBCC PAGE Mais je cherchais au mauvais endroit.

12
Simon Jones

Si vous pouvez accéder au DAC ( console d'administrateur dédié ), vous pouvez inspecter la valeur de la colonne d'identité pour INT colonnes, en regardant la colonne idtvalsys.syscolpars.

Merci à Martin Smith pour me diriger à cette table via cette réponse très utile par ROI Gavish sur une question connexe ici.

Prenez, par exemple, la table temporaire suivante:

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;

Voyons ce que la table contient:

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

La valeur d'identité peut être inspectée par ce code:

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           |
+----------------------+

Pour BIGINT colonnes d'identité, nous devons élargir la taille de certaines variables utilisées dans le code, telles que:

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);

Résultats pour le BIGINT:

+----------------------+
| CurrentIdentityValue |
+----------------------+
|                      |
| 9223372036854775704  |
+----------------------+
8
Max Vernon