我正在使用sql server 2008,其中我编写了一个存储过程,它在表中插入一些值,然后返回那些插入的值。我使用nvarchar
作为主键。因此,为了选择最后插入的值,我使用的是scopeidentity()
函数,但问题是它是插入值但不返回最后插入的值。代码如下:
CREATE PROCEDURE cms_AddOwnerSession
@sessionId nvarchar(max),
@ownerId int,
@ownerName nvarchar(50),
@username nvarchar(30),
@password nvarchar(30)
AS
BEGIN
IF(@sessionId <> NULL)
BEGIN
INSERT INTO OwnerSession
(SessionId,
OwnerId,
OwnerName,
Username,
[Password])
VALUES
(@sessionId,
@ownerId,
@ownerName,
@username,
@password)
SET @sessionId = SCOPE_IDENTITY()
END
SELECT
ISNULL (SessionId,'NULL') 'sessionId',
ISNULL (OwnerId,0) 'ownerId',
ISNULL (OwnerName,'') 'ownerName',
ISNULL (Username,'') 'username',
ISNULL ([Password],'') 'password'
FROM OwnerSession
WHERE SessionId = @sessionId
END
GO
答案 0 :(得分:2)
SCOPE_IDENTITY
返回上次生成的IDENTITY
列值。它与您自己提供的数据无关。它与第一列不匹配,并且与名称中包含“ID”的第一列不匹配。 (我认为其中一个就是误解)。
答案 1 :(得分:1)
scope_identity()返回在您的范围内生成的最后IDENTITY值。您的SessionId
不是身份证明
对scope_identity(), @@identity and IDENT_CURRENT值非常小心:
@@ IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT是类似的功能 因为它们都返回插入IDENTITY的最后一个值 一列表。
@@ IDENTITY和SCOPE_IDENTITY返回生成的最后一个标识值 在当前会话的任何表中。但是,SCOPE_IDENTITY返回 仅在当前范围内的值; @@ IDENTITY不限于此 具体范围。
IDENT_CURRENT不受范围和会话的限制;它仅限于a 指定表。 IDENT_CURRENT返回生成的标识值 对于任何会话和任何范围中的特定表。
答案 2 :(得分:1)
在您的上下文中scope_identity()
即使您使用了IDENTITY
列也无效,因为您尝试访问插入行的过程范围之外的值。要可靠地获取插入到过程中的值,您需要在同一语句中记录它,或者在使用IDENTITY
值时至少使用相同的过程。
在您的情况下,您可以获取提供的值并将其返回给调用者,或者您可以使用OUTPUT
子句来执行此操作。
可以在此处找到不同IDENTITY
相关功能的介绍和不足之处:http://sqlity.net/en/351/identity-crisis/
该文章还说明了OUTPUT
子句如何用于处理所有这些不足之处。
但请记住,如果插入完成并且您在执行期间没有捕获该值,则无法保证您之后将获得正确的值 - 与所使用的方法无关。