2011-08-29 102 views
0

的代码是这样的在存储过程

INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 

    GetLastInsertID @tablename='TABLE' 

GetLastInsertID使用@@ IDENTITY SCOPE_IDENTITY或()+插入,一起为这个存储过程:

SELECT @@IDENTITY AS LastID FROM TABLE 

如何获得存储过程按照上面Select @@ IDENTITY语句中的要求返回'LastID'?

我得到以下错误:

Incorrect syntax near 'GetLastInsertId'. 

...但是当自行执行这工作得很好:

GetLastInsertID @tablename='TABLE' 

好,谢谢,我更新,以SCOPE_IDENTITY()。但是你说不要把它放在一个不同的SP中,把它放在与Insert相同的SP中?

再说,我还是我得到一个错误,当我与此相结合的刀片:

SELECT SCOPE_IDENTITY() AS LastID FROM TABLE 

这里是新的错误消息:

There is already an object named 'TABLE' in the database. 
+4

使用[SCOPE_IDENTITY()](http://msdn.microsoft.com/en-us/library/ms190315.aspx)是优选的,而不是'@@ IDENTITY'。 –

+0

@Joe:请参阅[Joel的答案](http://stackoverflow.com/questions/7236141/using-identity-insert-together-in-stored-procedures/7236192#7236192),SCOPE_IDENTITY不起作用,因为存储 - 程序是一个不同的范围。 –

+0

请参阅[Identity Crisis](http://msdn.microsoft.com/zh-cn/library/aa224821(SQL.80).aspx)为什么@@ IDentity不好。它的一篇旧文章,但标题很容易记住 –

回答

5

这是一个坏主意,这个分离成因为存储过程会创建一个新的范围/上下文。这让你打开篡改错误的身份证号码。如果会话中的一个用户将多行记录在一起,您可能会得到错误的结果。

相反,您几乎总是希望使用scope_identity()函数,并且您想在与创建新记录的语句相同的上下文中调用它。

+0

不确定你的意思“如果会话中的一个用户插入多行,你可能会得到错误的结果。” AFAIK唯一的问题是触发器(以及具有并行性的错误,适用于'@@ IDENTITY'和'SCOPE_IDENTITY') –

+0

@Martin - 请参阅此[msdn page](http://msdn.microsoft.com/zh-cn/ /library/ms190315.aspx) - SCOPE_IDENTITY和@@ IDENTITY返回当前会话中任何表中生成的最后一个标识值。但是,SCOPE_IDENTITY返回仅在当前范围内插入的值; @@ IDENTITY不限于特定的范围。因此,即使范围不同,@@身份在任何时候在同一个会话中都有多个插入时都会遇到问题。触发器就是最常见的例子。 –

+1

@马丁 - 当然。存储过程(即:这个问题);) –

2

首先,你永远不想使用@@身份,因为如果有人添加触发器,它可能会中断。

你想要使用的是OUTPUT子句或scope_identity。请参阅联机丛书以了解如何使用OUTPUT的示例。

-1

这是我的示例代码,这样做。 (但存储的过程中不添加任何价值)

--First create a test table. 
    create table test 
    (id int identity, 
    name varchar(30)) 
    go 

--A stored proc that returns the scope_identity() 
    create proc dbo.spTest 
    as 

    insert into test(name) 
    values ('test') 

    return scope_identity() 

    go 


-- Sample call 
    declare @newId int 

    exec @newId = spTest 

    print @newId 
+0

SP看起来就像那样,但是当SP正在被保存/更改时它仍然给出错误: Msg 2714,数据库中已经有一个名为'spTest'的对象。 –

+0

将'return'混入是一个非常糟糕的主意,存储过程不应该使用'return'(可以将它用于SQL 2005之前的错误代码,但是现在可以使用RAISERROR并抛出)。使用一个OUTPUT参数。 –

+1

如果您已经有一个名为spTest的sp,您可以将“create proc”更改为“alter proc”。 – JBrooks

0

你的错误是在你的失败包括EXECUTE命令,试试这个:

INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 

EXEC GetLastInsertID @tablename='TABLE' 

假设EXEC当您尝试运行一个没有其他命令的过程,但是当包含INSERT时,它使得需要EXEC

现在,你真的需要确定你想要做的是一个好的设计。

尝试:

DECLARE @LastId int 
INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 
SELECT @LastID=SCOPE_IDENTITY() 
+0

你的第二个例子在上面的例子中产生错误。 –