T-SQL 标识值

/**********************************
        标识符 (IDENTITY) 值是一种特殊的值,它依赖于标识列,由SQL SERVER 自动维护,是自增的,而且一般是不会重复的.
但是SQL SERVER并不维护标识(IDENTITY) 值唯一(要保证标识值唯一,应该在该列上使用主键或者唯一键约束)

-----------------------------------------------------------------------------------------------------------

1、标识值不连续 
一般来说,出现下面的情况时,可能会导致 标识值不连续

A,事务回滚: 如果在插入数据时回滚事务,则插入记录时最后一个标识会被记录下来,下次插入的标识值就会不连续。
回滚事务包括手工事务的回滚和SQL SERVER 自动开启事务的回滚。
************************************/
USE TEST
GO


IF OBJECT_ID('TEMPDB..#A') IS NOT NULL
    DROP TABLE #A
GO

CREATE TABLE #A(
    ID INT IDENTITY(0,1) , 
    B INT UNIQUE
)

INSERT INTO #A(B) VALUES(1);
INSERT INTO #A(B) VALUES(2);

-- a.手工事务回滚
BEGIN TRAN
INSERT INTO #A(B) VALUES(3);
ROLLBACK TRAN

INSERT INTO #A(B) VALUES(3);

SELECT * FROM #A
/*    ID    B
    0    1
    1    2
    3    3    */

--b.因操作失败自动回滚事务
INSERT INTO #A(B) VALUES(3);
INSERT INTO #A(B) VALUES(4);

SELECT * FROM #A
/*    ID    B
    0    1
    1    2
    3    3
    5    4    

上面查询结果不存在标识 2 是因为手工回滚事务导致的, 不存在标识 3 是因为插入数据违反了唯一约束,自动回滚事务导致的 */

/*    B,删除记录:无论被删除记录的标识值是最新添加的,还是删除以前添加的记录,标识值均不会被回收再利用。
    因此,删除记录会导致标识值不连续                    */

IF OBJECT_ID('TEMPDB..#A') IS NOT NULL
    DROP TABLE #A
GO
CREATE TABLE #A(
    ID INT IDENTITY(0,1),
    B INT
)

INSERT INTO #A(B)
SELECT 1 UNION ALL
SELECT 2

--删除一条记录
DELETE FROM #A WHERE B = 2
INSERT INTO #A(B) VALUES(2)

SELECT * FROM #A
/* ID    B
    0    1
    2    2    
    从结果可以看到,标识值2并没有因为删除记录而回收,所以新增加记录的标识值仍然是3 */
DROP TABLE #A

/*    C,使用DBCC CHECKIDENT 重置标识值: 
    可以通过 DBCC CHECKIDENT 中的RESEED 选项重新设置指定表的当前标识值,重置标识值也可能会导致标识值不连续    */
IF OBJECT_ID('TEMPDB..#A') IS NOT NULL
    DROP TABLE #A
GO
CREATE TABLE #A(
    ID INT IDENTITY(0,1),
    B INT
)

INSERT INTO #A(B) VALUES(1)

--重置当前标识值
DBCC CHECKIDENT (#A , RESEED ,1 )
INSERT #A(B) VALUES (1)
SELECT * FROM #A
DROP TABLE #A
--DBCC CHECKIDENT 的用法:http://technet.microsoft.com/zh-cn/library/ms176057%28zh-tw,SQL.90%29.aspx
DBCC CHECKIDENT (#A  )
DBCC CHECKIDENT (#A , NORESEED )

/*
在第一次插入后,当前标识值为0 ,然后通过 DBCC CHECKIDENT 将当前标识设置为1,帮再次插入记录时,新插入记录的标识值为2
*/


/************************************
2,标识值重复:由于SQL SERVER 不维护标识值的唯一,因些在没有主键,唯一键等手段来维持标识值不重复的表中,
标识值可能会产生重复,导致标识重复的一般有以下两个情况:
A:强制插入标识值
************************************/

IF OBJECT_ID('TEMPDB..#A') IS NOT NULL
    DROP TABLE #A
GO
CREATE TABLE #A(
    ID INT IDENTITY(1,1),
    B INT
)

INSERT INTO #A(B) VALUES (1)

--插入重复的标识值
SET IDENTITY_INSERT #A ON 
INSERT INTO #A(ID ,B) VALUES (SCOPE_IDENTITY() ,2)
SET IDENTITY_INSERT #A OFF 

SELECT * FROM #A
DROP TABLE #A

/*    上述两条记录的标识值是一样的,因为第2条记录在插入时,强制指定了与第1条记录一样的标识值    
--------------------------------------------------------------------------------------
B, 使用DBCC CHECKIDENT 重置标识值: 如果重置标识值为一个比表中现有标识值更小的标识值(如果标识值增量为负数,则是比现有标识值更大),
    那么新插入列的标识值会重复            */


IF OBJECT_ID('TEMPDB..#A') IS NOT NULL
    DROP TABLE #A
GO
CREATE TABLE #A(
    ID INT IDENTITY(1,1),
    B INT
)
INSERT INTO #A(B) VALUES (1)
-- 重置标识值
DBCC CHECKIDENT(#A , RESEED , 0)
INSERT #A(B) VALUES(2)

SELECT * FROM #A
DROP TABLE #A
/* 第1次插入记录之后,当前的标识值为1,然后通过 DBCC CHECKIDENT 将当前标识值设置为 0 ,故再次插入记录时,新插入记录的标识值为1 */

参考:《SQL Server 2005开发、管理与应用实例》

posted @ 2012-12-06 16:48  _cc  阅读(836)  评论(0编辑  收藏  举报