Sql server 重置范围_标识()

Sql server 重置范围_标识(),sql-server,tsql,stored-procedures,Sql Server,Tsql,Stored Procedures,我有一个存储过程,它首先将一些数据插入临时表,然后将一行插入另一个表。我在第二次插入后调用Scope_Identity(),以获取新插入的记录标识 如果第二次插入由于连接而没有执行任何操作,我想检查Scope_标识并引发异常。但是Scope_Identity返回在第二次插入之前从临时表插入创建的最后一个标识 在调用第二次插入之前,是否有方法重置作用域标识,或者有更好的方法确定第二次插入是否确实没有插入任何内容?在第二次插入后立即检查@@ROWCOUNT。如果为0,则未插入任何行 INSERT I

我有一个存储过程,它首先将一些数据插入临时表,然后将一行插入另一个表。我在第二次插入后调用Scope_Identity(),以获取新插入的记录标识

如果第二次插入由于连接而没有执行任何操作,我想检查Scope_标识并引发异常。但是Scope_Identity返回在第二次插入之前从临时表插入创建的最后一个标识


在调用第二次插入之前,是否有方法重置作用域标识,或者有更好的方法确定第二次插入是否确实没有插入任何内容?

在第二次插入后立即检查
@@ROWCOUNT
。如果为0,则未插入任何行

INSERT INTO YourTable
SELECT ...

IF (@@ROWCOUNT = 0)
BEGIN
RAISERROR('Nothing inserted',16,1)
RETURN
END

@马丁·史密斯完全回答了你的问题(我比他投了更高的票)。

这显然是internet上唯一一个询问如何重置Scope_Identity()的页面。
我相信这对任何使用T-SQL的人来说都是至关重要的。

我将此答案留给前来寻找上一个insert语句插入的身份(而不是最后一个随机成功插入的身份)的任何人(像我一样)。

这就是我想到的:

SET @SomeID = (CASE WHEN @@ROWCOUNT > 0 THEN SCOPE_IDENTITY() ELSE NULL END)

我认为给出的其他答案可能更实用,但我确实想在这里记录我的发现,以防有朝一日对某人有所帮助。(这在SQL Server 2005中;不确定此行为是否在较新版本中持续存在。)

该技巧的基础是利用以下属性(来自联机丛书的文档中的
@@IDENTITY
):“在INSERT、SELECT INTO或bulk copy语句完成后…如果该语句不影响任何具有标识列的表,则。@@IDENTITY返回NULL。”虽然我找不到它的明确声明,这种行为似乎也适用于
SCOPE\u IDENTITY()
。因此,我们完成了一个
INSERT
语句,该语句不影响任何具有标识列的表:

CREATE TABLE NoIdentity (notId BIT NOT NULL)

-- An insert that actually inserts sets SCOPE_IDENTITY():
INSERT INTO YourTable (name)
SELECT 'a'
WHERE 1 = 1 -- simulate a join that yields rows

SELECT @@identity, SCOPE_IDENTITY()
-- 14, 14 (or similar)

-- The problem: an insert that doesn't insert any rows leaves SCOPE_IDENTITY() alone.
INSERT INTO YourTable (name)
SELECT 'a'
WHERE 1 = 0 -- simulate a join that yields no rows

SELECT @@identity, SCOPE_IDENTITY()
-- Still 14, 14 . . . how do we know we didn't insert any rows?

-- Now for the trick:
INSERT INTO NoIdentity (notId)
SELECT 0
WHERE 1 = 0 -- we don't actually need to insert any rows for this to work

SELECT @@identity, SCOPE_IDENTITY()
-- NULL, NULL.  Magic!

INSERT INTO YourTable (name)
SELECT 'a'
WHERE 1 = 0 -- simulate a join that yields no rows

SELECT @@identity, SCOPE_IDENTITY()
-- Still NULL, NULL since we didn't insert anything.  But if we had, it would be non-NULL.
-- We can tell the difference!
所以,就你的情况而言,你似乎可以

INSERT INTO NoIdentity (notId)
SELECT 0
WHERE 1 = 0

要在执行第二次
插入之前重置
SCOPE\u IDENTITY()

在考虑了几个备选方案后,我发现自己喜欢在以下方面重复:

正如您从我最后的
SELECT CASE…
中所看到的,在我的情况下,我试图以一个
INT NOT NULL
结束,这将帮助我了解是否插入了一行(在这种情况下,我需要它的ID)。(如果可能的话,我不建议一开始就处于这种情况!)您将如何处理
@result
取决于您需要做什么

我喜欢
插入
@result
之间的关系是明确的,不太可能受到我可能没有想到的其他干预操作的影响。我还喜欢
@result
自然地处理插入多行的情况

INSERT INTO YourTable
SELECT ...

IF (@@ROWCOUNT = 0)
BEGIN
RAISERROR('Nothing inserted',16,1)
RETURN
END