SQL Server 重置Identity標識列的值(INT爆了)

轉自: https://www.cnblogs.com/gaizai/archive/2013/04/23/3038318.htmlhtml

1、背景
  SQL Server數據庫中表A中Id字段的定義是:[Id] [int] IDENTITY(1,1),隨着數據的不斷增加,Id值已經接近2147483647(int的取值範圍爲:-2 147 483 648 到 2 147 483 647)了,雖然已經對舊數據進行歸檔,可是這個表須要保留最近的1億數據,有什麼方法解決Id值就快爆的問題呢?
  解決上面的問題有兩個辦法:一個是修改表結構,把Id的int數據類型修改成bigint;第二個是重置Id(Identity標識列)的值,使它從新增加。
  當前標識值:current identity value,用於記錄和保存最後一次系統分配的Id值;下次分配Id就是:當前標識值+標識增量(一般爲+1,也能夠自行設置);
  當前列值:current column value,這Id值到目前爲止的最大值;數據庫

2、重置過程
(一) 下面就測試重置Identity標識列,首先使用下面的SQL建立測試表:markdown

--建立測試表
CREATE TABLE [dbo].[Test_Identity](
[IdentityId] [int] IDENTITY(1,1) NOT NULL,
[Name] nchar NULL,
CONSTRAINT [PK_testid] PRIMARY KEY CLUSTERED
(
[IdentityId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]ide

(二) 顯示插入Id值,插入後表[Test_Identity]的記錄如Figure1所示,接着再隱式插入Id值,插入後表[Test_Identity]的記錄如Figure2所示。測試

--顯示插入Id值
SET IDENTITY_INSERT [Test_Identity] ON
INSERT INTO Test_Identity
SELECT 1000,'name1'
SET IDENTITY_INSERT [Test_Identity] OFFcode

--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name2'htm

(Figure1:數據記錄)對象

(Figure2:數據記錄)
(三) DBCC CHECKIDENT('table_name', NORESEED)不重置當前標識值。DBCC CHECKIDENT 返回一個報表,它指明當前標識值和應有的標識值。執行下面的SQL語句,返回的信息表示:當前標識值'1001',當前列值'1001',如Figure2所示。blog

--查詢標識值
DBCC CHECKIDENT('Test_Identity', NORESEED)
/
檢查標識信息: 當前標識值'1001',當前列值'1001'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/rem

(四) 再隱式插入Id值,插入後表[Test_Identity]的記錄如Figure3所示。因此執行上面的SQL語句是不會重置當前標識值的,能夠放心執行。
--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name3'

(Figure3:數據記錄)

--查詢標識值
DBCC CHECKIDENT('Test_Identity', NORESEED)
/
檢查標識信息: 當前標識值'1002',當前列值'1002'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/

(五) DBCC CHECKIDENT ('table_name') 或DBCC CHECKIDENT ('table_name', RESEED) 若是表的當前標識值小於列中存儲的最大標識值,則使用標識列中的最大值對其進行重置。
由於上面返回結果是:當前標識值'1002',當前列值'1002',因此執行下面的SQL語句是沒有影響的,何時纔有影響呢?參考:(當在Figure4狀態下執行下面的SQL命令,結果就會如Figure7所示)

--重置標識值
DBCC CHECKIDENT('Test_Identity', RESEED)
/
檢查標識信息: 當前標識值'1002',當前列值'1002'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/

(六) DBCC CHECKIDENT('table_name', RESEED, new_reseed_value)當前值設置爲 new_reseed_value。若是自建立表後沒有將行插入該表,則在執行 DBCC CHECKIDENT 後插入的第一行將使用 new_reseed_value 做爲標識。不然,下一個插入的行將使用 new_reseed_value + 1。若是 new_reseed_value 的值小於標識列中的最大值,之後引用該表時將產生 2627 號錯誤信息。
要理解上面的描述,能夠進行下面的測試:
1) 從新設置當前值設置爲new_reseed_value = 995,執行下面的SQL語句返回的信息以下所示;

--重置標識值
DBCC CHECKIDENT('Test_Identity', RESEED, 995)
/
檢查標識信息: 當前標識值'1002',當前列值'995'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/

2) 繼續往[Test_Identity]表插入數據,執行下面的SQL語句插入後的結果如Figure4所示;插入的Id值爲new_reseed_value + 1 = 996;
--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name4'

(Figure4:數據記錄)
3) 查看如今的標識值,與上面的進行對比,你就能夠理解【當前標識值】與【當前列值】的意義了;

--查詢標識值
DBCC CHECKIDENT('Test_Identity', NORESEED)
/
檢查標識信息: 當前標識值'996',當前列值'1002'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/

4) 繼續往[Test_Identity]表插入數據,執行3次後表的數據如Figure5所示;
--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name5'

(Figure5:數據記錄)
5) 若是如今繼續往[Test_Identity]表插入數據會發生什麼事情呢?將產生 2627 號錯誤信息,以下面的錯誤信息;
消息2627,級別14,狀態1,第2 行
違反了PRIMARY KEY 約束'PK_testid'。不能在對象'dbo.Test_Identity' 中插入重複鍵。
語句已終止。
6) 下面來測試建立表後沒有插入行,若是這個時候執行重置標識值會發生什麼事情?清空[Test_Identity]表,再從新設置標識值,返回的信息以下面所示;

--清空表
truncate table [Test_Identity]
--重置標識值
DBCC CHECKIDENT('Test_Identity', RESEED, 995)
/
檢查標識信息: 當前標識值'NULL',當前列值'995'。
DBCC 執行完畢。若是DBCC 輸出了錯誤信息,請與系統管理員聯繫。
/

7) 這個時候往[Test_Identity]表插入數據,數據就如Figure6所示,這說明了:「若是自建立表後沒有將行插入該表,則在執行 DBCC CHECKIDENT 後插入的第一行將使用 new_reseed_value 做爲標識。」
--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name5'

(Figure6:數據記錄)

(Figure7:數據記錄)
8) 假如咱們刪除了IdentityId爲1000和1001的記錄,這個時候繼續插入數據,會從新生成1000和10001值嗎?效果如Figure10所示(從新覆蓋了);
--刪除和
delete from [Test_Identity] where IdentityId=1000
delete from [Test_Identity] where IdentityId=1001

(Figure8:數據記錄)
--重置標識值
DBCC CHECKIDENT('Test_Identity', RESEED, 996)
--隱式插入Id值
INSERT INTO Test_Identity
SELECT 'name6'

(Figure9:數據記錄)

(Figure10:數據記錄)
(七) 總結:到這裏,咱們已經能夠解決Id值就快爆的問題了,由於咱們舊的數據會定時歸檔,因此不會出現2627錯誤信息;而另一個場景是當出現Figure5的時候,能夠執行DBCC CHECKIDENT('Test_Identity', RESEED),設置爲當前列最大值爲標識值,防止出現2627錯誤信息。

3、補充說明
在MySQL中,也有相似Identity的功能:
IDs int(11) unsigned NOT NULL AUTO_INCREMENT在建立表的時候,會有一個選項AUTO_INCREMENT=17422061,直接能夠設置起始值,還能夠設置步長:SHOW VARIABLES LIKE 'auto_inc%';起始值:auto_increment_offset步長:auto_increment_incrementSET @auto_increment_increment=10;SELECT LAST_INSERT_ID();

相關文章
相關標籤/搜索