简体   繁体   中英

how to use SCOPE_IDENTITY() not in insert

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

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM