SQL Server ->> 数据类型函数 DATALENGTH \IDENT_CURRENT \IDENT_INCR \IDENT_SEED \IDENTITY


DATALENGTH

返回传入数据真实数据占用子节(bytes)存储大小。举例,把 数值=1的整型传入会得到4,因为整型会占用4个子节长度的数据存储。而如果1是字符,返回1,如果1是unicode,返回2。讲到DATALENGTH,自然会联想到另外一个函数LEN。LEN只适用于字符,而DATALENGTH是多种数据类型都支持。LEN只关心字符的实际长度,不关系存储空间。

SELECT DATALENGTH(N'1'),LEN(N'1'),DATALENGTH('1'),LEN('1'),DATALENGTH(1),LEN(1)

结果

IDENT_CURRENT

返回表当前的占用掉的最大自增列的数值。如果返回NULL值,说明表从来没有插入任何数据行或者表被截断过。

讲到IDENT_CURRENT就不得不讲其他两个同样用于获取自增值的函数:@@IDENTITY和SCOPE_IDENTITY

  • IDENT_CURRENT 返回为某个会话和用域中的指定表生成的最新标识值。
  • @@IDENTITY 返回为跨所有作用域的当前会话中的任何表生成的最后一个标识值。
  • SCOPE_IDENTITY 返回为当前会话和当前作用域中的某个表生成的最新标识值。

意思就是IDENT_CURRENT返回的是指定表的最新标示值,至于标识值是否是已提交事务则不一定。SCOPE_IDENTITY则是当前会话作用域内产生的最新标示值,假设说有个会话,会话先插入数据到表A,调用了存储过程A,存储过程啥也没干,就输出这个SCOPE_IDENTITY值,会得到表A的自增列值吗? 答案是不会。SCOPE_IDENTITY的限制到当前作用域,如果当前作用域里面没有任何的数据插入,SCOPE_IDENTITY就不会产生任何值。

MSDN也提醒了“请谨慎使用 IDENT_CURRENT 来预测下一个生成的标识值。 由于其他会话执行的插入,实际生成的值可能与 IDENT_CURRENT 加上 IDENT_INCR 不同。”

因为IDENT_CURRENT不同于SCOPE_IDENTITY。后者的前提是当前作用域(例如存储过程)已经执行过数据插入到目标表,假设已经开启事务,那么SCOPE_IDENTITY紧随在INSERT语句后面,这个时候INSERT语句发生的时候已经对表申请了排他锁,其他并发会话是需要等待当前事务提交才能执行数据插入,所以它获取的SCOPE_IDENTITY值+1是可以预估下一行数据的自增列值的。而IDENT_CURRENT不是当前作用域级别,不会随当前事务锁定表,如果其他会话事务插入数据到表,不管事务是否提交,只要INSERT语句没有被堵塞,意味着自增列值已经增加,所以IDENT_CURRENT+1有可能是错误的。

CREATE TABLE dbo.TEST_SCOPE_IDENTITY
(
    ID INT IDENTITY(1,1),
    COL1 NVARCHAR(50)
)


CREATE PROCEDURE dbo.sp_TEST_SCOPE_IDENTITY
AS 

SELECT SCOPE_IDENTITY()
GO
INSERT INTO  dbo.TEST_SCOPE_IDENTITY VALUES('')
SELECT SCOPE_IDENTITY()

EXEC sp_TEST_SCOPE_IDENTITY

IDENT_INCR 和 IDENT_SEED

IDENT_INCR返回表的自增列每次递增的值,IDENT_SEED是表的自增列递增起始种子,这个数值可以通过调用DBCC CHECKIDENT命令修改

IDENTITY

在select into 新表的时候可以自动创建自增列

--(1)  
SELECT IDENTITY(int, 1,1) AS ID_Num  
INTO NewTable  
FROM OldTable;  
  
--(2)  
SELECT ID_Num = IDENTITY(int, 1, 1)  
INTO NewTable  
FROM OldTable;