Wo speichert SQL Server den IDENTITY VALUE für eine Tabelle physisch?

12

Ich hoffe, jemand kann mich in die richtige Richtung lenken. Hier sind meine bisherigen Ergebnisse.

SELECT * FROM sys.identity_columnsist eine Systemansicht, die "last_value" ergibt, aber die Definition für diese Ansicht verwendet eine interne Funktion IdentityProperty(colName, 'LastValue')- das ist also eine Sackgasse (sie wird dort nicht aus einer Systemtabelle gezogen ).

Überall im Internet (habe ich nachgesehen) schlägt die Verwendung von DBCC IDENT_...Befehlen vor, um den Wert aufzudecken, aber das lässt mich immer noch im Dunkeln darüber, wo er tatsächlich gespeichert ist.

Ich bin also dazu gekommen, die einzelnen Seiten mit DBCC PAGE(TestDB,1,1325,3)meinem Testgeschirr db RESEEDzu durchsuchen und mit dem Befehl zwischen den Werten 10 und 12 neu zu säen.

Dabei dies, bemerkte ich die Hex - Werte auf das IAM: Header, IAM: Single Page Allocationsund IAM: Extent Alloc Status Slot 1alles änderte sich . (Und erkannte, dass sie sich ohnehin periodisch ändern, zusammen mit dem Wert von bUse1 , der sich ebenfalls inkrementell von selbst ändert).

Also noch eine Sackgasse und mir fehlen alle Ideen. Wo kann ich noch suchen?

Ich führe SQL Server 2014 aus. Ich habe einen unstillbaren Durst nach internen Kenntnissen und muss noch auf etwas stoßen, das so schwer zu fassen ist. Es ist mir aufgefallen, weil es theoretisch (ein absoluter Wert) irgendwo gespeichert ist und (wohl) lokalisierbar sein sollte. Auf meiner Suche nach Orten intern gespeicherter Daten / Metadaten erscheint mir dieser besondere Wert besonders schwer fassbar. Ich vermute / hoffe, dass jemand mitkommt und mir sagt, dass Sie es mitbekommen können, DBCC PAGEaber ich habe an der falschen Stelle gesucht.

Simon Jones
quelle

Antworten:

8

Wenn Sie auf die DAC ( Dedicated Administrator Console ) zugreifen können , können Sie den Wert der Identitätsspalte auf INTSpalten überprüfen , indem Sie sich die idtvalSpalte in ansehen sys.syscolpars.

Vielen Dank an Martin Smith , der mich über diese sehr nützliche Antwort von Roi Gavish auf eine verwandte Frage an diesen Tisch weitergeleitet hat.

Nehmen Sie zum Beispiel die folgende temporäre Tabelle:

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;

Mal sehen, was die Tabelle enthält:

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

Der Identitätswert kann mit diesem Code überprüft werden:

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

Für BIGINTIdentitätsspalten müssen wir die Größe einiger im Code verwendeter Variablen erweitern, beispielsweise:

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

Ergebnisse für die BIGINT:

+----------------------+
| CurrentIdentityValue |
+----------------------+
|                      |
| 9223372036854775704  |
+----------------------+
Max Vernon
quelle