Sql-Server
有沒有辦法查看 SQL Server 2012 如何定義新身份?
關於
Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64)
,有沒有辦法查看 SQL Server 使用什麼機制來計算由創建的表的新標識值SELECT INTO
?樣本數據
-- Create our base table CREATE TABLE dbo.A (A_ID INT IDENTITY(1, 1), x1 INT, noise1 int DEFAULT 1, noise2 char(1) DEFAULT 'S', noise3 date DEFAULT GETUTCDATE(), noise4 bit DEFAULT 0); -- Create random data between the range of [0-3] INSERT INTO dbo.A(x1) SELECT s1000.n FROM ( SELECT TOP (10) n = 1 FROM sys.columns) AS s10 -- 10 CROSS JOIN ( SELECT TOP (10) n = 1 FROM sys.columns) AS s100 -- 10 * 10 CROSS JOIN ( SELECT TOP (10) n = ABS(CHECKSUM(NEWID())) % 4 FROM sys.columns) AS s1000; -- 100 * 10 SELECT * FROM dbo.A ORDER BY A_ID DESC;
就我而言,結果是:
並執行
DBCC CHECKIDENT('A')
返回
檢查身份資訊:目前身份值'1000’,目前列值'1000’。
創建新表
當我們將一個子集選擇到一個新表中時,它會創建一個新的目前標識值:
SELECT * INTO #temp FROM dbo.A WHERE x1 = 0;
這個新表的標識列中的最大值是 998,當我們檢查它的下一個標識時:
DBCC CHECKIDENT('#temp')
檢查身份資訊:目前身份值'998’,目前列值'998’。
如何?
如何將這些標識值插入到新表中,並將最高值正確設置為新表的目前標識值?
SELECT INTO
有兩個階段(在執行計劃中不可見)。首先,它創建一個與用於創建它的查詢的元數據相匹配的表。這發生在系統事務中,因此(空)創建的表將繼續存在,即使它
SELECT INTO
被包裝在回滾的使用者事務中。在第一階段結束時,我們有一個空表,其中包含一個名為A_ID的列和標識屬性。第二階段在第一階段創建的表中執行插入操作。此插入是使用identity_insert語義完成的,因此源表中的標識值最終在目標中,不變。實際插入的最大值被設置為最後使用的值。您可以使用
IDENT_CURRENT
sys.indentity_columns來查看它。不相關但半有趣的事實:在創建表和開始執行插入之間有一個小視窗,其中查詢中的源表不受模式穩定性鎖的保護。如果並發程序碰巧更改了源表的架構(在創建目標之後,但在插入開始之前),則會引發錯誤 539:
創建目標表後,架構發生了變化。重新執行 Select Into 查詢。