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;