2009-01-23 66 views
50

我使用此代碼重置在表中標識:DBCC CHECKIDENT設置標識爲0

DBCC CHECKIDENT('TableName', RESEED, 0) 

也能正常工作的大部分時間,用我插入1到ID列的第一個插入。但是,如果我刪除數據庫並重新創建它(使用我已寫入的腳本),然後調用DBCC CHECKIDENT,則插入的第一項將具有ID爲0.

任何想法?

編輯:研究後,我發現我沒有正確讀取的文檔: http://msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx - 「當前標識值設置爲new_reseed_value如果沒有行已經插入表中,因爲它被創造了,執行DBCC CHECKIDENT將使用new_reseed_value作爲標識之後插入的第一行。否則,下一行插入將使用new_reseed_value + 1「。

回答

17

正如你在你的問題中指出這是一個documented behavior。但我仍然覺得很奇怪。我用來重新填充測試數據庫,即使我不依賴於標識字段的值,當從頭開始填充數據庫並刪除所有數據並重新填充後,有不同的值會有不同的值。

一個可能的解決方案是使用truncate清理表而不是刪除。但是之後您需要放棄所有約束,然後重新創建它們

以這種方式,它總是表現爲新創建的表並且不需要調用DBCC CHECKIDENT。第一個標識值會在表定義中所指定的,這將是相同的,無論你插入數據的第一次或N次

+1

鏈接似乎已死,目前的文檔https://msdn.microsoft.com/en-us/library/ms176057.aspx,表示這只是2012年之前版本的預期行爲,但這似乎不是真的(測試在2012版本中,兼容性設置爲2012年,仍然存在問題)。 – jmoreno 2017-02-07 21:09:56

5

變化語句

DBCC CHECKIDENT('TableName', RESEED, 1) 

這將從開始2(或1磨片ñ你重新創建表),但它永遠不會是0.

42

你是對的,題。

運行DBCC CHECKIDENT('TableName', RESEED, 0)後:
- 新創建的表將開始與認同0
- 現有的表將繼續與認同1

的解決方案是在下面的腳本,這有點差的芒截形的:)

-- Remove all records from the Table 
DELETE FROM TableName 

-- Use sys.identity_columns to see if there was a last known identity value 
-- for the Table. If there was one, the Table is not new and needs a reset 
IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'TableName' AND last_value IS NOT NULL) 
    DBCC CHECKIDENT (TableName, RESEED, 0); 
+1

非常好,但是在處理多個模式時,您可能需要稍微調整一下以匹配`object_id`而不是使用`OBJECT_NAME()`查找表名:`IF EXISTS(SELECT * FROM sys.identity_columns WHERE object_id = OBJECT_ID('Schema.TableName')AND last_value IS NOT NULL`) – Nick 2016-11-29 20:00:14

1

我做了這個作爲實驗重置值爲0,因爲我想我的第一個標識列爲0,它的工作。

dbcc CHECKIDENT(MOVIE,RESEED,0) 
dbcc CHECKIDENT(MOVIE,RESEED,-1) 
DBCC CHECKIDENT(MOVIE,NORESEED) 
1
USE AdventureWorks2012; 
GO 
DBCC CHECKIDENT ('Person.AddressType', RESEED, 0); 
GO 



AdventureWorks2012=Your databasename 
Person.AddressType=Your tablename 
1

我在SQL中使用這個身份設置爲特定值: -

DECLARE @ID int = 42; 
DECLARE @TABLENAME varchar(50) = 'tablename' 

DECLARE @SQL nvarchar(1000) = 'IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '''[email protected]+''' AND last_value IS NOT NULL) 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID-1)+'); 
    END 
    ELSE 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID)+'); 
    END'; 
EXEC (@SQL); 

這在C#中設置一個特定值: -

SetIdentity(context, "tablename", 42); 
. 
. 
private static void SetIdentity(DbContext context, string table,int id) 
{ 
    string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '" + table 
     + "' AND last_value IS NOT NULL)\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id - 1).ToString() + ");\n"; 
    str += "END\nELSE\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id).ToString() + ");\n"; 
    str += "END\n"; 
    context.Database.ExecuteSqlCommand(str); 
} 

這建立在上述答案上,並始終確保下一個值是42(在這種情況下)。

0

看起來很荒謬的是,您無法使用單個命令設置/重置標識列以涵蓋表是否插入了記錄。我無法理解我遇到的行爲,直到我偶然發現上面的問題!我的解決方案 - 醜,但工程 - 是明確檢查sys.identity_columns.last_value表,告訴你該表是否已插入的記錄,並在每種情況下調用相應的DBCC CHECKIDENT命令: DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT ('MyTable', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed); END