Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Best way to get last ID?

Author  Topic 

tech1
Starting Member

49 Posts

Posted - 2012-02-07 : 11:31:34
What is the best way of obtaining the last generated ID or a new ID for a bigint column?

I want to make sure there wont be any "clashes" across all sessions.

I know we have Scope_Identity and Ident_Current('tableName') but which is better?

I do believe Ident_Current is better but would appreciate your thoughts. I just need the next ID available so I can insert it into related tables.

Thanks

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2012-02-07 : 12:15:45
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-02-07 : 12:42:28
quote:
Originally posted by tech1

What is the best way of obtaining the last generated ID or a new ID for a bigint column?

I want to make sure there wont be any "clashes" across all sessions.

I know we have Scope_Identity and Ident_Current('tableName') but which is better?

I do believe Ident_Current is better but would appreciate your thoughts. I just need the next ID available so I can insert it into related tables.

Thanks


is it always single row insertion or batch insertion?

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-02-07 : 13:13:32
DECALRE @Rowcount int, @Error int, @Scope_Identity int

INSERT Statement...

SELECT @Rowcount = @@ROWCOUNT
, @Error = @@ERROR
, @Scope_Identity = SCOPE_IDENTITY()

..do error/logic handlingl

...use @Scope_Identity as the key for additional processing against?

BOL:

http://msdn.microsoft.com/en-us/library/ms190315.aspx

[/quote]
SCOPE_IDENTITY, IDENT_CURRENT, and @@IDENTITY are similar functions because they return values that are inserted into identity columns.

IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the value generated for a specific table in any session and any scope. For more information, see IDENT_CURRENT (Transact-SQL).

SCOPE_IDENTITY and @@IDENTITY return the last identity values that are generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.

For example, there are two tables, T1 and T2, and an INSERT trigger is defined on T1. When a row is inserted to T1, the trigger fires and inserts a row in T2. This scenario illustrates two scopes: the insert on T1, and the insert on T2 by the trigger.

Assuming that both T1 and T2 have identity columns, @@IDENTITY and SCOPE_IDENTITY will return different values at the end of an INSERT statement on T1. @@IDENTITY will return the last identity column value inserted across any scope in the current session. This is the value inserted in T2. SCOPE_IDENTITY() will return the IDENTITY value inserted in T1. This was the last insert that occurred in the same scope. The SCOPE_IDENTITY() function will return the null value if the function is invoked before any INSERT statements into an identity column occur in the scope.

Failed statements and transactions can change the current identity for a table and create gaps in the identity column values. The identity value is never rolled back even though the transaction that tried to insert the value into the table is not committed. For example, if an INSERT statement fails because of an IGNORE_DUP_KEY violation, the current identity value for the table is still incremented.


[/bol]



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-02-07 : 13:21:00
well then there is this?

http://connect.microsoft.com/SQLServer/feedback/details/328811/scope-identity-sometimes-returns-incorrect-value

I suggest you use Natural Keys instead of surrogatyes anyway



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2012-02-07 : 13:41:17
"Best way to get last ID?"

What's the underlying problem that you are trying to solve? (or avoid !!)
Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-02-07 : 13:45:52
quote:
Originally posted by tech1
I do believe Ident_Current is better

Thanks



You have choosen....poorly



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2012-02-07 : 14:11:54
quote:
Originally posted by tech1

I do believe Ident_Current is better but would appreciate your thoughts.


So if two users insert at the same time, you want both of them to get the same value back, the higher of the identity values that the two of them inserted?

Have you considered using the OUTPUT clause?

--
Gail Shaw
SQL Server MVP
Go to Top of Page

tech1
Starting Member

49 Posts

Posted - 2012-02-08 : 03:10:19
What does the output parameter have to do with anything in this case? :-)
I am certainly using that to return the userID back to the client/.NET but I want the DB to be the one to get the last possible ID available for the user.

so if Ident_current is "poor" (from what I was reading on MSDN, it seemed the right choice because it takes into consideration all sessions and ALL scopes, rather than just the current session and current scope), then what am I left with? SCOPE_IDENTITY?
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2012-02-08 : 06:45:01
quote:
Originally posted by tech1

What does the output parameter have to do with anything in this case? :-)


If that was directed at me, I said nothing about output parameter. I asked if you'd considered the output clause in an insert statement

quote:
so if Ident_current is "poor" (from what I was reading on MSDN, it seemed the right choice because it takes into consideration all sessions and ALL scopes, rather than just the current session and current scope), then what am I left with? SCOPE_IDENTITY?


@@identity if you have no triggers on the tables, Scope identity or the output clause.

Ident_current does not tell you what identity value you inserted was, it tells you just what the identity value is for the table across all sessions by all users. That's a major risk for race conditions. Try this:

-- setup code, run first

use tempDB;
go

create table TestingIdentity (
ID int identity,
UserName varchar(10)
)

CREATE TABLE [dbo].[Results](
[IdThatThisSessionInserted] [int] NULL,
[IdentCurrent] [numeric](38, 0) NULL,
[SessionName] [varchar](10) NULL
)

go


In query window 1:

SET NOCOUNT ON
go

WAITFOR TIME '13:37' -- set to a couple minutes time so that all 3 start together.
go

INSERT INTO TestingIdentity (UserName) VALUES ('Session 1')

-- This will get the latest row that this session inserted
INSERT INTO dbo.Results
( IdThatThisSessionInserted ,
IdentCurrent ,
SessionName
)
SELECT TOP 1 ID AS IdThatThisSessionInserted, IDENT_CURRENT('TestingIdentity') AS IdentCurrent, UserName AS SessionName
FROM TestingIdentity
WHERE UserName = 'Session 1'
ORDER BY ID DESC

GO 200


in query window 2:

SET NOCOUNT ON
go

WAITFOR TIME '13:37'-- set to the same time as window 1
go

INSERT INTO TestingIdentity (UserName) VALUES ('Session 2')

-- This will get the latest row that this session inserted
INSERT INTO dbo.Results
( IdThatThisSessionInserted ,
IdentCurrent ,
SessionName
)
SELECT TOP 1 ID AS IdThatThisSessionInserted, IDENT_CURRENT('TestingIdentity') AS IdentCurrent, UserName AS SessionName
FROM TestingIdentity
WHERE UserName = 'Session 2'
ORDER BY ID DESC

GO 200


in query window 3
SET NOCOUNT ON
go

WAITFOR TIME '13:37' -- set to same time as window 1
go

INSERT INTO TestingIdentity (UserName) VALUES ('Session 3')

-- This will get the latest row that this session inserted
INSERT INTO dbo.Results
( IdThatThisSessionInserted ,
IdentCurrent ,
SessionName
)
SELECT TOP 1 ID AS IdThatThisSessionInserted, IDENT_CURRENT('TestingIdentity') AS IdentCurrent, UserName AS SessionName
FROM TestingIdentity
WHERE UserName = 'Session 3'
ORDER BY ID DESC

GO 200


Run all three simultaneously and wait until they're finished. Once they're all done...

SELECT * FROM dbo.Results AS r WHERE IdThatThisSessionInserted != IdentCurrent


I got 158 results in my first test. Pretty impressive since only 600 rows were inserted in total. In other words, in 25% of the cases, ident_current returned an identity value that a completely different session had inserted, one that was no relation at all to the row that had just been inserted by that session.

--
Gail Shaw
SQL Server MVP
Go to Top of Page

DonAtWork
Master Smack Fu Yak Hacker

2167 Posts

Posted - 2012-02-08 : 07:03:53
Kristen asked once: What is the problem you are trying to solve? You seem to be asking "Should i use a crowbar, a hammer, or a brick?" and we have NO idea what you are trying to do.






http://weblogs.sqlteam.com/jeffs/archive/2008/05/13/question-needed-not-answer.aspx
How to ask: http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx

For ultra basic questions, follow these links.
http://www.sql-tutorial.net/
http://www.firstsql.com/tutor.htm
http://www.w3schools.com/sql/default.asp
Go to Top of Page

tech1
Starting Member

49 Posts

Posted - 2012-02-08 : 07:47:04
Thanks all.

Don: the problem is that I need the userID returned back to .NET via the output param. Thats ok but I need to know what the userID will be when the record has been inserted into the User table, as then I need to insert data into the next related table in the same SPROC and using that userID as the referencing ID
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2012-02-08 : 08:14:51
Then you need the UserID from the record you have JUST inserted. Either use OUTPUT or scope_identity() [if you have a oolumn in the table that has the IDENTITY property)
Go to Top of Page

tech1
Starting Member

49 Posts

Posted - 2012-02-08 : 08:19:49
yes thats exactly what the question is :-)
should I use Scope_Identity, @@Identity, Ident_current?

I always use Scope_Identity but just want to make sure im not missing something.
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2012-02-08 : 09:36:34
Go have a look at my nice long example of why ident_current is a poor idea (unless you like incorrect results part of the time)

As for how you do it
quote:
@@identity if you have no triggers on the tables, Scope identity or the output clause.


--
Gail Shaw
SQL Server MVP
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2012-02-08 : 09:41:42
quote:
Originally posted by tech1

yes thats exactly what the question is :-)
should I use Scope_Identity, @@Identity, Ident_current?


I just answered that, or do you need some clarification of the answer I gave you?
Go to Top of Page

tech1
Starting Member

49 Posts

Posted - 2012-02-08 : 10:02:00
Hmm. thanks Kristen
Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 2012-02-08 : 11:02:12
what am I? Chopped Liver?

mmmmmmmm



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/


Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2012-02-08 : 13:55:58
quote:
Originally posted by X002548

what am I? Chopped Liver?

mmmmmmmm



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Want to help yourself?

http://msdn.microsoft.com/en-us/library/ms130214.aspx

http://weblogs.sqlteam.com/brettk/

http://brettkaiser.blogspot.com/




Implying that you aren't?
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-02-08 : 14:10:42
quote:
Originally posted by tech1

Hmm. thanks Kristen


best way is to use output clause to capture id generated by getting it from inserted table. This even works for batch insertions and you can capture ids generated in a temporary table if you want

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page
   

- Advertisement -