SQL Server 將表的 IDENTITY VALUE 物理儲存在哪裡?
我希望有人能在這個問題上指出我正確的方向。這是我到目前為止的工作。
SELECT * FROM sys.identity_columns
是一個系統視圖,它提供“last_value”,但該視圖的定義使用內部函式IdentityProperty(colName, 'LastValue')
- 所以這是一個死胡同(不是從那裡的系統表中拉出來的)。網際網路上的任何地方(我看過)都建議使用
DBCC IDENT_...
命令來發現價值,但這仍然讓我對它的實際儲存位置一無所知。
DBCC PAGE(TestDB,1,1325,3)
因此,我開始使用我的測試工具 db搜尋各個頁面,並使用RESEED
命令在值 10 和 12 之間重新設置種子。在這樣做時,我注意到 , 上的十六進制值
IAM: Header
都IAM: Single Page Allocations
發生IAM: Extent Alloc Status Slot 1
了變化。(並意識到它們會隨著bUse1值的變化而周期性變化,bUse1 值也會自行遞增)。所以另一個死胡同,我完全沒有想法。我還能在哪裡搜尋?
我正在執行 SQL Server 2014。我對內部知識有著永不滿足的渴望,並且還沒有遇到像這樣難以捉摸的東西。它引起了我的注意,因為從理論上講,它(絕對值)儲存在某個地方並且應該(可以說)是可定位的。在我尋找內部儲存數據/元數據位置的過程中,這個特殊的價值讓我覺得特別難以捉摸。我猜/希望有人會過來告訴我,你可以得到它,
DBCC PAGE
但我找錯地方了。
如果您可以訪問 DAC(專用管理員控制台
INT
),則可以通過查看 中的idtval
列來檢查列的標識列的值sys.syscolpars
。感謝Martin Smith通過Roi Gavish對此處相關問題的這個非常有用的回答將我引導到該表。
以下面的臨時表為例:
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;
讓我們看看表包含的內容:
SELECT * FROM #d;
+------------+ | ID | +------------+ | 2147483635 | +------------+
可以通過以下程式碼檢查身份值:
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 | +----------------------+
對於
BIGINT
標識列,我們需要擴展程式碼中使用的一些變數的大小,例如: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);
結果
BIGINT
:+----------------------+ | CurrentIdentityValue | +----------------------+ | | | 9223372036854775704 | +----------------------+