简体   繁体   中英

Get MAX id number from database table after deleting last record

I want to get a new row id for "products", for this I use MAX SQL command as follwing (the command is in insert new record button click event):

SqlCommand cmd = new SqlCommand("Select ISNULL(MAX(id)+1,0) from products", SqlCon);

the issue is when there are rows with IDs 10,11,12 (12 is MAX) and i delete id 12 record , i gets MAX+1 id 12 when the new id row is 13 ("id" field is PK with identity increment 1). can i do it with other way?

example:

id  prodect
--  -------
1     dog
2     cat
3     mouse
4     elefant

when i deletes row 4 i get MAX(id)+1 = 4 and i want to get 5 since this is the next row id.

I will take a stab at what I think you are after. :)

If you include SELECT SCOPE_IDENTITY(); in your SQL you will get the ID you need:

INSERT INTO products (
   * your fields *
)
VALUES (
   * your values *
);
SELECT SCOPE_IDENTITY();

And then in your code you can have:

var Id = Convert.ToInt32(cmd.ExecuteScalar());

This will give you the id of the record you have inserted.

I suspect the actual question is How can I find the ID of the row I just inserted so I can use it as a foreign key in related tables or in an image file name?

SQL Server since 2005 provides the OUTPUT clause in INSERT, UPDATE, DELETE statements that returns the values of the columns just inserted or modified. In the case of the insert statement, the syntax is:

insert into Products (Product)
OUTPUT inserted.ID 
VALUES ('xxx')

This is a better option than the IDENT_CURRENT or SCOPE_IDENTITY values because it returns the values using a single statement and there is no ambiguity about what is returned:

  • IDENT_CURRENT may return a different value if multiple users are writing to the table outside a transaction
  • SCOPE_IDENTITY returns the last ID generated in a transaction, no matter the table

You can return more than one column:

insert into Products (Product)
OUTPUT inserted.ID, inserted.Product
VALUES ('xxx')

You can execute this statement with ExecuteScalar, if you return only one column or ExecuteReader, if you want to return more columns.

In the case of UPDATE or DELETE statements, the deleted table contains the deleted values and inserted contains the new values

Note ORMs like Entity Framework use such statements already to retrieve auto-generated IDs and update saved objects. In this case one only needs to read the ID property of the saved objects.

One possible solution could be that you don't delete the rows. You can add a flag and make it inactive/deleted. That way your row numbers will always be preserved and your code will give you the max Id.

I think the OP tries to tackle the wrong problem...

When you insert a new product into the products table, you should try to retrieve the new id directly with the scope_identity function as such (SQLServer!):

string sql = "insert into products(name) values('Yellow Cup'); SELECT SCOPE_IDENTITY();";
var sqlCommand = new SqlCommand(sql, conn);
var id = cSqlServer.ExecuteScalar();

Definitely MAX is not what anybody would use in this case. Closest solution would be to get recently used identity value and then increment it by 1 (in your case) or by seed value, whatever it is.

select ident_current('products') + 1

Caution - although this solves your purpose for now, beware that 'ident_current' will return you the identity value set by other sessions as well. In simple words, if there is some request/trigger/execution that causes id to be incremented even before your button click finishes then you you will get inserted_id and not deleted one.

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