1

I want to get new id(Identity) before insert it. so, use this code:

select SCOPE_IDENTITY()  AS NewId from tblName

but is get this:

1- Null

2- Null

Matt
  • 3,638
  • 2
  • 26
  • 33
kaka mishoo
  • 231
  • 1
  • 2
  • 9
  • 3
    Why do you need the value before insert? – Martin Smith Dec 19 '14 at 21:58
  • Is there an identity specification on a column in that table? – Eric Hauenstein Dec 19 '14 at 21:58
  • @MartinSmith : I want show this code to the user – kaka mishoo Dec 19 '14 at 22:00
  • 1
    No you don't want to get the new identity before you insert it. The way you would do that is with IDENT_CURRENT. This however is a BAD idea because of concurrency. Have you read about SCOPE_IDENTITY? It will return the last identity value in the current scope. If you haven't inserted a row to a table with an identity it will return NULL because there is no value. – Sean Lange Dec 19 '14 at 22:01
  • @EricHauenstein : Yse. this name is (Id) – kaka mishoo Dec 19 '14 at 22:01
  • 1
    Why do you want to show the identity to the user? – Sean Lange Dec 19 '14 at 22:01
  • NO do NOT use @@IDENTITY here. That is a horrible suggestion. You should read and understand what that does. It returns the last inserted identity for the current connection. This will also be NULL. – Sean Lange Dec 19 '14 at 22:03
  • @SeanLange : I dont use IDENT_CURRENT. Because This however is a BAD idea because of concurrency. – kaka mishoo Dec 19 '14 at 22:04
  • 1
    Well you would need to reserve the number to stop another session using it then if you're showing it to the user. Simplest way would be to do a poor man's simulation of a sequence by inserting to another table with an identity column and using the identity allocated from that. But why does the user need to know this before insert anyway? – Martin Smith Dec 19 '14 at 22:04
  • @MartinSmith that doesn't solve the concurrency issue at all. It just makes it more complicated. If two people are using the same process you have the same issue. – Sean Lange Dec 19 '14 at 22:05
  • @SeanLange yes it does. The same identity won't be issued twice. – Martin Smith Dec 19 '14 at 22:06
  • @MartinSmith ahh I see what you are saying about the table...do that insert first and get the value back. Gotcha. – Sean Lange Dec 19 '14 at 22:07
  • @SeanLange yes. It can just be a single column table with an `identity` column and an insert `default values` to get an identity value to use. – Martin Smith Dec 19 '14 at 22:08
  • Suggest you take a look at this: http://stackoverflow.com/questions/810962/getting-new-ids-after-insert-in-sql-server-2008 – spender Dec 19 '14 at 23:06

4 Answers4

3

This is too verbose for a comment.

Consider how flawed this concept really is. The identity property is a running tally of the number of attempted inserts. You are wanting to return to the user the identity of a row that does not yet exist. Consider what would happen if you have values in the insert that cause it too fail. You already told the user what the identity would be but the insert failed so that identity has already been consumed. You should report to the user the value when the row actually exists, which is after the insert.

Sean Lange
  • 33,028
  • 3
  • 25
  • 40
  • Ok, so i changed it to, i have use this in insert and new filde. please help me for this in Entity framework. but i get SCOPE_IDENTITY() before insert id. – kaka mishoo Dec 19 '14 at 22:17
  • You can't use SCOPE_IDENTITY to get the value of the row before you insert it. It doesn't exist. Plain and simple. There is no work around if you are going to use an identity in the same table as the data. – Sean Lange Dec 19 '14 at 22:19
  • I have use new id in record. (Id=1,Name=aa,Code=aa1).(Id=2,Name=bb,Code=bb2). Code = Name + Id. – kaka mishoo Dec 19 '14 at 22:23
  • 1
    @kakamishoo So a field on your object needs to be concatenated with the new identity value? You can't do this the way you are trying. You'll have to call context.SaveChanges() then do your concatenation on the same object instance. Then SaveChanges() again. – Matt Dec 19 '14 at 22:36
3

COMPUTED COLUMN VERSION

You'll have to do this on the sql server to add the column.

alter table TableName add Code as (name + cast(id as varchar(200)))

Now your result set will always have Code as the name + id value, nice because this column will remain updated with that expression even if the field are changed (such as name).


Entity Framework Option (Less ideal)

You mentioned you are using Entity Framework. You need to concatenate the ID on a field within the same record during insert. There is no capacity in SQL (outside of Triggers) or Entity Framework to do what you are wanting in one step.

You need to do something like this:

var obj = new Thing{ field1= "some value", field2 = ""};
context.ThingTable.Add(obj);
context.SaveChanges();
obj.field2 = "bb" + obj.id; //after the first SaveChanges is when your id field would be populated
context.SaveChanges();

ORIGINAL Answer: If you really must show this value to the user then the safe way to do it would be something like this:

begin tran
insert into test(test) values('this is something')
declare @pk int = scope_identity()
print @pk

You can now return the value in @pk and let the user determine if its acceptable. If it is then issue a COMMIT else issue the ROLLBACK command.

This however is not a very good design and I would think a misuse of the how identity values are generated. Also you should know if you perform a rollback, the ID that would of been used is lost and wont' be used again.

Matt
  • 3,638
  • 2
  • 26
  • 33
  • 1
    And lock the system for an indeterminate length of time until the user submits? – Martin Smith Dec 19 '14 at 22:25
  • Wouldn't that just lock the table with the pending insert? Not the entire DB. – Matt Dec 19 '14 at 22:28
  • I have use new id in record. (Id=1,Name=aa,Code=aa1).(Id=2,Name=bb,Code=bb2). Code = Name + Id – kaka mishoo Dec 19 '14 at 22:29
  • @Matt. Yes, but that's still pretty severe and there are better alternatives if this is even really needed at all. – Martin Smith Dec 19 '14 at 22:30
  • Yes it would lock that table. What happens when another person wants to insert a row? Or what if the system is a web application? Transactions like that should not be used in web apps because the table would be locked until the connection pool reclaims that connection if the user loses connectivity. – Sean Lange Dec 19 '14 at 22:30
  • 1
    That's what I thought. Not sure why the OP has to know the value before hand, doesn't make sense to me. Just was trying to come up with some sort of way to pull it off, even if its a horrible idea to begin with. – Matt Dec 19 '14 at 22:32
  • @kakamishoo See the new answer, this might help you. – Matt Dec 19 '14 at 22:44
  • 1
    "No capacity outside triggers". A computed column can do this. No need to persist it even. – Martin Smith Dec 19 '14 at 22:47
  • Is this the correct answer? I'm twice connect to the database? also code is Unique, but not null insert... – kaka mishoo Dec 19 '14 at 22:47
  • @MartinSmith I ALWAYS forget about computed columns! I updated answer to reflect that as an option. Good call. – Matt Dec 19 '14 at 22:53
1

I can't understand why you want to show that identity to user before insert, I believe (as @SeanLange said) that is not custom and not useful, but if you insist I think you can do some infirm ways. One of them is

  • 1) Insert new row then get ID with SCOPE_IDENTITY() and show to user
  • 2) Then if you want to cancel operation delete the row and reset
    identity (if necessary) with DBCC CHECKIDENT('[Table Name]', RESEED, [Identity Seed]) method

Other way is not using the Identity column and manage id column by yourself and it must be clear this approach can't be work in concurrency scenarios.

QMaster
  • 3,743
  • 3
  • 43
  • 56
  • but I have use new id in record. (Id=1,Name=aa,Code=aa1).(Id=2,Name=bb,Code=bb2). Code = Name + Id. not problem in use on the network? How can I use it? – kaka mishoo Dec 19 '14 at 22:36
  • @kakamishoo Please more describe. I can't understand what you want to do exactly. If you can please improve your question with more details or tell me here. – QMaster Dec 19 '14 at 22:45
  • I have 'Code' in table. it is = Name + Id. For example, (1,AAA,AAA1),(2,BBB,BB2),... so, I should Id in Code. – kaka mishoo Dec 19 '14 at 22:54
  • That is not matter. You can insert record as i said before then show to user and if that is acceptable then 'update' the Code column with id and if that is not acceptable delete and reset identity as i said before too. Please accept my post as answer if you satisfied. – QMaster Dec 19 '14 at 22:59
0

I think perhaps you're confusing the SQL identity with a ORACLE sequence. They work completely different. With the ORACLE sequence you'll get the sequence before you insert the record. With a SQL Identity, the last identity generated AFTER the insert in available via the SCOPE_IDENTITY() function.

If you really need to show the ID to the user before the insert, your best bet is to keep a counter in a separate table, and read the current value, and increment that by one. As long as "gaps" in the numbers aren't a problem.

Spock
  • 4,700
  • 2
  • 16
  • 21