SQL Server在哪里将表的IDENTITY VALUE物理存储在哪里?


12

我希望有人可以指出我在这个方向上的正确方向。到目前为止,这是我的工作。

SELECT * FROM sys.identity_columns是一个提供“ last_value”的系统视图,但是该视图的定义使用了内部函数IdentityProperty(colName, 'LastValue')-因此是死胡同(不是从系统表中拉出它)。

互联网上的任何地方(我看过的地方)都建议使用DBCC IDENT_...命令来发现该值,但这仍然使我不清楚其实际存储位置。

因此,我开始DBCC PAGE(TestDB,1,1325,3)针对测试工具数据库搜索单个页面,并使用RESEED命令在值10和12之间重新设定种子。

在执行此操作时,我注意到上的十六进制值IAM: HeaderIAM: Single Page Allocations并且IAM: Extent Alloc Status Slot 1所有值都已更改。(并且意识到它们无论如何都会随着bUse1值的变化而定期变化,而bUse1值本身也会逐渐变化)。

所以另一个死胡同,我全都没主意了。我还能在哪里搜索?

我正在运行SQL Server2014。我对内部知识有无限的渴望,并且还没有遇到像这样难以捉摸的东西。它引起了我的注意,因为从理论上讲,它(一个绝对值)存储在某个位置,并且应该(可以说)是可定位的。在我探索内部存储的数据/元数据的位置时,这个特殊的值使我感到难以捉摸。我猜测/希望有人会来告诉我,您可以接受,DBCC PAGE但我找错了地方。

Answers:


8

如果您可以访问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  |
+----------------------+
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.