- 1. IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值。
- 缺点:不局限当前会话,其它会话新增会有问题。
- 2. @@IDENTITY 返回为当前会话的所有作用域中的任何表最后生成的标识值。
- 缺点:如果有触发器,会弄错。
- 3. SCOPE_IDENTITY 返回为当前会话和当前作用域中的任何表最后生成的标识值。
- 缺点:暂时没发现。
USE tempdb
GO
IF OBJECT_ID('t1') IS NOT NULL
DROP TABLE t1
GO
IF OBJECT_ID('t2') IS NOT NULL
DROP TABLE t2
GO
GO
CREATE TABLE t1(id int IDENTITY)
CREATE TABLE t2(id int IDENTITY(100,1))
GO
CREATE TRIGGER trig_t1_I
ON t1
FOR INSERT
AS
BEGIN
INSERT t2 DEFAULT VALUES
END
GO
SELECT * FROM t1
SELECT * FROM t2
--------- 以上为测试表及测试的触发器,表中数据均为空 ----------
------- 第 1 个窗口执行查询 -------
INSERT t1 DEFAULT VALUES
SELECT @@IDENTITY
/*
100
注:返回的是触发器中的 t2 的新增标识列的值。@@IDENTITY所取得的ID号就是最后一个作用域产生的结果
*/
SELECT SCOPE_IDENTITY()
/*
1
注:返回的是当前作用域的新增标识列的值
*/
SELECT IDENT_CURRENT('t2')
/*
100
注:返回的是 t2 表的新增标识列的值
*/
SELECT IDENT_CURRENT('t1')
/*
1
注:返回的是 t1 表的新增标识列的值
*/
------- 第 2 个窗口执行查询 -------
SELECT @@IDENTITY
/*
NULL
注:因为当前会话窗口,没有执行过标识列表的操作
*/
SELECT SCOPE_IDENTITY()
/*
NULL
注:因为当前会话窗口,没有执行过标识列表的操作
*/
SELECT IDENT_CURRENT('t1')
/*
1
t1 表最后的值
*/
SELECT IDENT_CURRENT('t2')
/*
100
t2 表最后的值
*/
如果你不想看那么多,简单来说就是 SCOPE_IDENTITY() 就合适你了。
下面是测试 IDENT_CURRENT 在并发下出错的脚本:
测试工具:SqlServer并发测试工具SqlQueryStress
--------------------------------- 下面是 IDENT_CURRENT 测试脚本 -----------------------------------------
预备脚本:
CREATE TABLE bm(
bmId INT IDENTITY(1,1) PRIMARY KEY,
courseName VARCHAR(10) NOT NULL,
addTime DATETIME NOT NULL,
payId INT NOT NULL
)
GO
CREATE TABLE pay(
payId INT IDENTITY(1,1) PRIMARY KEY,
courseName VARCHAR(10) NOT NULL,
addTime DATETIME NOT NULL
)
GO
并发测试脚本:
DECLARE @bmId INT,@payId INT,@courseName VARCHAR(10),@tmp INT
SELECT @courseName=RIGHT(NEWID(),1)
INSERT INTO bm(courseName,addTime,payId) VALUES(@courseName,GETDATE(),0);
SELECT @bmId= ident_current('bm');
INSERT INTO pay(courseName,addTime) VALUES(@courseName,GETDATE());
SELECT @payId= ident_current('pay');
UPDATE bm SET payId=@payId WHERE bmId=@bmId
并发工具:
测试结果检验:
SELECT * FROM dbo.bm AS a INNER JOIN dbo.pay AS b
ON a.payId=b.payId
WHERE a.courseName!=b.courseName
由上可知:在大并发情况下:ident_current 函数是不安全的,不要用。
--------------------------------- 下面是 SCOPE_IDENTITY 测试脚本 -----------------------------------------
先删除且中所记录:
truncate table bm;
truncate table pay;
并发测试脚本:
DECLARE @bmId INT,@payId INT,@courseName VARCHAR(10),@tmp INT
SELECT @courseName=RIGHT(NEWID(),1)
INSERT INTO bm(courseName,addTime,payId) VALUES(@courseName,GETDATE(),0);
SELECT @bmId= SCOPE_IDENTITY();
INSERT INTO pay(courseName,addTime) VALUES(@courseName,GETDATE());
SELECT @payId= SCOPE_IDENTITY();
UPDATE bm SET payId=@payId WHERE bmId=@bmId
结果:无错误记录